Go中包含有CGI包,net/http/cgi,这篇文章就是来阅读和使用这个包。关于cgi的参数和运行,可以看这篇文章:CGI的一些知识点

CGI包阅读

cgi包的存在就告诉我们一件事情,cgi服务端和客户端完全可以使用Go来写

这个包其实很简单,只有两个文件,其他都是测试程序

child.go

host.go

host.go是可以直接宿主到go的web服务器上的代码,里面提供了对request和response的直接处理函数ServerHTTP, 当你是使用go的http包写了个http之后,就可以使用ServerHTTP对请求直接配置上cgi,有点像apache中自带了php-cgi

child.go则是已经进入到脚本子进程中了,如果你的CGI脚本是go代码生成的可执行脚本,那么你就会有用到这个文件里面的函数了。这个文件内提供了将命令行环境(CGI请求)转换成Go的http包中的request的方法。

host.go是cgi的启动父程序需要用到的包,child.go是子程序需要用到的包

先看host.go

首先是trailingPort,这个变量是cgi服务器监听的端口号,(比如在nginx中我们一般都监听9000)

然后是osDefaultInheritEnv,这个map将各个平台的共享库默认路径列出来了。为什么设置这个变量呢?这样说,由于cgi服务器执行命令的时候命令查找设置参数有的是去环境变量中获取的,因此对每个命令执行需要设置一下环境变量。而在不同的平台,动态库的路径是不一样的,所以有了这么个Map。

Handler是在子程序中执行cgi脚本的。里面要注意的结构是两个Env和InheritEnv两个,一个是特别设定的环境变量,另外一个是继承的环境变量。

还有Handler中的Path,就是执行文件的路径,比如/test.php

下面就是最重要的ServeHTTP了,这个是用来回调处理HTTP请求的,它会将HTTP请求转化为CGI请求,并且执行这个cgi脚本。

在这个函数中,能看到CGI的RFC标准参数赋值,然后可以看到拼出了env之后将env作为exec.Cmd的Env来调用cgi脚本(path)。同时也看到了当body内有content的时候,会将Body作为stdin输入,然后从stdout出来的东西逐行读取,然后读取到header和body中去。

看了host.go的实现就很好理解child.go的实现了。

从Serve(handler)来看,先是使用将nginx提供的cgi请求转换成为net包中的http request和response,如果你有设置handler,就用request和response来进行处理。

后续的几个操作Write,Flush都已经是简单的buffer处理了。

CGI包使用

然后自然想到的一个问题,能不能实现

go-web服务器 + go-cgi + cgi-script

这个是可以做的,而且也不复杂:

代码如下:

package main
import(
  "net/http/cgi"
  "log"
  "net/http"
)
func main() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
    handler := new(cgi.Handler)
    handler.Path = "/home/yejianfeng/go/gopath/src/cgi-script/" + r.URL.Path
    log.Println(handler.Path)
    handler.Dir = "/home/yejianfeng/go/gopath/src/cgi-script/"
    handler.ServeHTTP(w, r)
  })
  log.Fatal(http.ListenAndServe(":8989",nil))
}

如果你在cgi-script中有个可运行的cgi脚本,比如test.perl

那么我们就可以在浏览器中调用http://10.16.15.64:8989/test.perl

来进行脚本调用

然后进一步想,能不能把go代码当作是php这样的动态脚本来运行呢,这样就可以一边修改go源码,一边就可以在页面中立刻显示修改结果了。即

go-web + go-cgi + go-cgi-script?

答案同样也是可以,但是这个时候由于xx.go并非是可执行文件,只能使用go run 来进行调用。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import(
  "net/http/cgi"
  "log"
  "net/http"
)
func main() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
    handler := new(cgi.Handler)
    handler.Path = "/home/yejianfeng/bin/go"
    script := "/home/yejianfeng/go/gopath/src/cgi-script/" + r.URL.Path
    log.Println(handler.Path)
    handler.Dir = "/home/yejianfeng/go/gopath/src/cgi-script/"
    args := []string{"run", script}
    handler.Args = append(handler.Args, args...)
    handler.Env = append(handler.Env, "GOPATH=/home/yejianfeng/go/gopath")
    handler.Env = append(handler.Env, "GOROOT=/home/yejianfeng/go/go")
    log.Println(handler.Args)
    handler.ServeHTTP(w, r)
  })
  log.Fatal(http.ListenAndServe(":8989",nil))
}

然后在cgi-script文件夹中建立test.go

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import(
  "fmt"
)
func init() {
  fmt.Print("Content-Type: text/plain;charset=utf-8\n\n");
}
func main() {
  fmt.Println("This is go test!!!!")
}

这里的init()是必须打印出来的

然后就可以打印出页面了

这时候go就像php脚本一样,如果你修改了test.go就能立刻在页面上显示出来了

对于第二种,当然也可以使用监控文件夹的修改等,当go项目修改后就重新build出一个可执行脚本,然后cgi的handler就修改下路由指向到这个可执行脚本。

关于监控文件的项目现在已经有很多开源的了:比如这个https://github.com/jianfengye/go-superviser

Ps: 文中说的例子已经加到http://go.funaio.com/pkg/net/http/cgi/ 的Example中了。

本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2012/12/25/2831891.html,如需转载请自行联系原作者

Go中的CGI包使用相关推荐

  1. 使用govendor灵活管理Go程序中的依赖包

    业务痛点 使用Go开发程序的过程中,为了方便开发,往往会引用很多标准库或者第三方的依赖包,第三方依赖包往往比标准库功能更全面更强大更接地气,那么如何管理众多的第三方依赖包呢?如何更新其版本?在不需要时 ...

  2. helm部署仓库中没有的包_Kubernetes的Helm软件包管理器简介

    helm部署仓库中没有的包 Before we dive into the Helm package manager, I'm going to explain some key concepts t ...

  3. 面试官问:你来讲下Netty通信中的粘包、拆包?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:Java技术剑 来源:https://urlify.cn/I ...

  4. python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比

    python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比 目录

  5. python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比、自定义设置每一个数据格的颜色

    python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比.自定义设置每一个数据格的颜色 目录

  6. python中使用squarify包可视化treemap图:使用treemap图可视化个人或者集体的股票、基金的持仓结构(treemap with squarify package)

    python中使用squarify包可视化treemap图:使用treemap图可视化个人或者集体的股票.基金的持仓结构(treemap with squarify package) 目录

  7. pycharm中导出依赖包 在pycharm下边的Terminal打开命令行终端执行命令

    pycharm中导出依赖包 1 在pycharm下边的Terminal打开命令行终端执行命令 D:\nlp\salary\aSalary>pip freeze > d:\nlp\salar ...

  8. Win7在IIS7中启用CGI

    IIS7启用CGI,本人在iis6中配置过*.cgi文件的执行,写此文章讲述怎样在IIS7中启用cgi脚本执行功能.本人的操作系统为Windows7. 第一步:保证CGI已经安装,如未安装请如下安装: ...

  9. ssh升级后+sftp+java_java中使用JSCH包,SFTP及SSH2文件操作及远程命令执行(改进)...

    我写过一篇java中使用JSCH包,SFTP及SSH2文件操作及远程命令执行,现在想来,觉得调用方式太过于绕,不符合我写程序的风格,所以进行了改进. 参数类,用于配置连接的参数,SshConfigur ...

最新文章

  1. vue 去除路由时候的#
  2. AOP开发——在不修改源代码的前提下,对类里面的方法进行增强 : 前置 后置 环绕 异常||如何得到目标方法的参数和返回值
  3. python static 的用法_Python中static相关知识小结
  4. Linux内存管理:MMU那些事儿
  5. 计算机毕业设计中Java编程案例之学生管理系统
  6. STC学习:霍尔开关器件
  7. Prometheus和Grafana监控实践
  8. python的基础语法
  9. 自定义竖着的SeekBar
  10. java 获取IP地址 无法获取到真实的IP地址
  11. python 获取搜狗输入法里面所有的表情图片
  12. 科技学术论文润色经验——分享1
  13. 【Java----函数(function)】
  14. 全球及中国柔性AMOLED面板行业消费量调研及投资前景预测报告2022-2028年
  15. SCHURTER概况以及产品应用(一)+代理商渠道
  16. 解决WIn7无线网图标显示不正确的问题
  17. 阿里巴巴2016算法岗实习招聘(西安)在线笔试整理
  18. 从python菜鸟到kaggle_Kaggle首次定义数据科学家:30岁,年薪5万刀,爱Python,最恨脏数据-阿里云开发者社区...
  19. html5爱心鱼游戏教程,HTML5小游戏---爱心鱼(上)
  20. 视频文件格式和视频编码方式的区别

热门文章

  1. 学习编程可能会走哪些弯路,有哪些经验可以参考?
  2. SaaS应用的十二要素
  3. 互联网时代的融媒技术
  4. 2022年全国大学生智能汽车竞赛西部赛 竞赛方案与实施流程
  5. html新罗马字体样式,新罗马字体怎么设置,新罗马字体设置教程
  6. elasticsearch集群搭建记录
  7. 实战-源码编译搭建LAMP环境
  8. centos7系统关机命令_centos7正确关机重启
  9. Python爬虫入门教程,突破煎蛋网反爬措施,妹子图批量抓取!
  10. 《飞桨PaddleSpeech语音技术课程》一句话语音合成全流程实践