[color=indigo][size=medium][b]需求:用一个golang 文件去编译批量的go文件[/b][/size][/color]
[color=red][size=large][b]一:访问需要编译的文件[/b][/size][/color]
[size=medium]为什么要有这样的需求?总不可能又很多要go文件的情况下,你去一个一个的执行吧,那显然是不聪明的做法,于是就有了这样的需求。想要去编译批量文件,首先需要做的就是先要找到,只有找到了我们想要的文件才能进行编译,这个前提不能少。那么golang官方文档提供我们去访问目录的方法为path包下的filepath包中的Walk方法。引入相关包以及查询文件代码如下[/size]:
[size=medium]当go run 该文件后(要加路径名!!!),效果如如下:[/size]
[img]http://dl2.iteye.com/upload/attachment/0099/5148/debfaf4a-9af0-3bac-96f6-d18830ddeab7.jpg[/img]
[size=medium]下面来稍做分析,对于接收命令行参数就我知道的有两种方法,一种就是我用到的。另外一种如下:[/size]
[b]但是这种做法存在一种缺点,那就是一旦该walk函数执行完毕找到的文件信息也就消失了:那么是否可以封装该匿名函数方法,将读取到的文件信息保存与自己定义的文件结构体中呢?[/b][/size]
[size=medium]这样以来,我们就封装好了查看目录的方法,相应的我们调用Walk方法时稍做修改:[/size]
[size=medium]这样就能避免必须要在匿名函数中区操作文件了,因为你已经保存了,该修改部分参考原文[url]http://www.ohlinux.com/archives/818/[/url]当做到这里的时候你是不是觉得已经离需求很近很近了?答案必须是肯定的。文件我们已经得到了,现在主要就是对这些批文件进行编译了。要程序实现构建go文件,那么就只有调用shell命令了:[/size]
[size=medium]剩下的问题就是要去拼接shell命令了,然后将拼接好的传递该方法就ok啦!:[/size]
[size=medium]能够调用方法了,我们是不是把他们否封装在一个编译文件方法里去调用会更好呢:[/size]
[size=medium]最后就只需要对每一个文件调用buildFile就好了!!!一举攻下它[/size]
[img]http://dl2.iteye.com/upload/attachment/0099/5160/da727008-4832-3f9d-98d4-1b6a2895e11d.jpg[/img]
[size=medium]这样变完成了所需的了,用一个文件就能编译出整个目标文件夹下的所有go文件并生成可执行文件了!!!
[/size]
[size=large][b]二:感想[/b]
对于使用新的golang语言其实感觉还是很不错的,简单说说我觉得的优点吧
1.没有那么多硬性的规定,比如每行都不需加要分号,这里编译时会自动加上
2.在判断的时候不需要圆括号
3.可以返回多值
4.自动匹配类型用起来特别爽
当然也有很烦人的地方,当控制语句之有一条语句同样需要用{}括起来。总体来说还不错吧。
今天就到这里了。
[/size]
[color=red][size=large][b]一:访问需要编译的文件[/b][/size][/color]
[size=medium]为什么要有这样的需求?总不可能又很多要go文件的情况下,你去一个一个的执行吧,那显然是不聪明的做法,于是就有了这样的需求。想要去编译批量文件,首先需要做的就是先要找到,只有找到了我们想要的文件才能进行编译,这个前提不能少。那么golang官方文档提供我们去访问目录的方法为path包下的filepath包中的Walk方法。引入相关包以及查询文件代码如下[/size]:
package main
imoport(
"path/filepath"
"fmt"
"os"
)
/**查询文件信息根据传来的参数作为walk()方法的root节点*/
func queryFile(){
flag.Parse()
root:=flag.Arg(0)
if root==""{
log.Fatal("请输入要查询的目录位置:")
}
err :=filepath.Walk(root,func(path string,f os.FileInfo,err error) error {
fmt.Println("f...",f.Name())
})
if err!= nil{
fmt.Println("filePath.Walk return:%v \n",err)
}
}
func main(){
queryFile()
}
[size=medium]当go run 该文件后(要加路径名!!!),效果如如下:[/size]
[img]http://dl2.iteye.com/upload/attachment/0099/5148/debfaf4a-9af0-3bac-96f6-d18830ddeab7.jpg[/img]
[size=medium]下面来稍做分析,对于接收命令行参数就我知道的有两种方法,一种就是我用到的。另外一种如下:[/size]
commandPath:=os.Args
if len(commandPath)==1{
log.Fatal("请输入参数")
}
root:commandPath[1]
[size=medium]两种的唯一不同就是后面这种命令行参数是作为下标为1所在的地方。看了文档很久,也就大概才理解到“因为是下面这种模式下把前面的执行语句也当做是一个参数了,但是上面一种因为在调用flag.Parse()方法时没有对flag参数进行定义,所以命令行输入的才算真正开始。不知道这种理解对不对。在来看下面的Walk方法,主要就是里面的那个func(...)匿名函数起作用,找到文件夹并遍历都是由它来完成。
[b]但是这种做法存在一种缺点,那就是一旦该walk函数执行完毕找到的文件信息也就消失了:那么是否可以封装该匿名函数方法,将读取到的文件信息保存与自己定义的文件结构体中呢?[/b][/size]
/****定义一个用于保存文件信息的结构体*/
type sysFile struct{
fName string
fSize int64
fIsDir bool
}
/**保存文件的目录结构*/
type F struct{
file []*sysFile
}
/***封装一个查看目录结构的方法同时将目录中的文件信息记录起来*/
func (self *F)visit(path string,info os.FileInfo,err error) error{
if (info==nil){
return err
}
//存储文件信息,这这里就保存了文件名,大小,是否为文件
infoFile:=&sysFile{
fName: info.Name(),
fSize: info.Size(),
fIsDir: info.IsDir(),
}
self.file=append(self.file,infoFile)
return nil
}
[size=medium]这样以来,我们就封装好了查看目录的方法,相应的我们调用Walk方法时稍做修改:[/size]
self:=F{
file:make([]*sysFile,0),
}
err :=filepath.Walk(root,func(path string,f os.FileInfo,err error) error {
return self.visit(path,f,err)
})
[size=medium]这样就能避免必须要在匿名函数中区操作文件了,因为你已经保存了,该修改部分参考原文[url]http://www.ohlinux.com/archives/818/[/url]当做到这里的时候你是不是觉得已经离需求很近很近了?答案必须是肯定的。文件我们已经得到了,现在主要就是对这些批文件进行编译了。要程序实现构建go文件,那么就只有调用shell命令了:[/size]
/**根据command的不同执行相关shell 命令*/
func invokeCommand(command string){
if command==" "{
return
}
cmd:=exec.Command("/bin/sh","-c",command)
err:=cmd.Run()
if err!= nil{
fmt.Println(command,"操作失败!")
return
}
}
[size=medium]剩下的问题就是要去拼接shell命令了,然后将拼接好的传递该方法就ok啦!:[/size]
/**根据参数fileName判断是否为go文件,并且拼接shell命令*/
func pingCommand(fileName string){
//拼接好需要编译的命令与文件名字符串(go build +fileName)
//筛选为所有go文件才执行
if !strings.HasSuffix(fileName,".go"){
fmt.Println(fileName,"不是go文件,不进行编译")
return
}
command:=`go build `+fileName
invokeCommand(command)
/***将编译好的文移动到与批文件目录下同级的bin目录下aimDir**/
execFileName:=strings.TrimSuffix(fileName,".go")
mvCommand :=`mv `+execFileName+` `+aimDir
invokeCommand(mvCommand)
}
[size=medium]能够调用方法了,我们是不是把他们否封装在一个编译文件方法里去调用会更好呢:[/size]
/***根据文件夹名编译里面的所有go文件,在这里还是要将go build当做shell 命令去调用*/
func buildFile(self F){
//1.首先先创建一个bin目录,用于保存编译后产生的可执行文件
cmd:=`mkdir `+aimDir
invokeCommand(cmd)
//调用pingCommand()方法
fmt.Println()
for _,v:=range self.file{
if !v.fIsDir{
pingCommand(v.fName)
}
}
}
[size=medium]最后就只需要对每一个文件调用buildFile就好了!!!一举攻下它[/size]
[img]http://dl2.iteye.com/upload/attachment/0099/5160/da727008-4832-3f9d-98d4-1b6a2895e11d.jpg[/img]
[size=medium]这样变完成了所需的了,用一个文件就能编译出整个目标文件夹下的所有go文件并生成可执行文件了!!!
[/size]
[size=large][b]二:感想[/b]
对于使用新的golang语言其实感觉还是很不错的,简单说说我觉得的优点吧
1.没有那么多硬性的规定,比如每行都不需加要分号,这里编译时会自动加上
2.在判断的时候不需要圆括号
3.可以返回多值
4.自动匹配类型用起来特别爽
当然也有很烦人的地方,当控制语句之有一条语句同样需要用{}括起来。总体来说还不错吧。
今天就到这里了。
[/size]