golang学习笔记(一)

golang学习笔记(一)

编译

能否编译成静态exe,不需要go环境。

可以。使用命令:go build

使编译的exe有图标

  • 安装rsrc
go get github.com/akavel/rsrc
go install github.com/akavel/rsrc
  • 在go项目根目录下创建manifest文件, 命名随意,如:icon.manifest,内容为:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="x86"
    name="controls"
    type="win32"
></assemblyIdentity>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="*"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        ></assemblyIdentity>
    </dependentAssembly>
</dependency>
</assembly>
  • 把ico文件复制到go项目根目录下,如 myico.ico
  • 执行命令,生成syso文件,名字可以随意。如main.syso
rsrc -manifest icon.manifest -ico myico.ico -o main.syso
  • 执行go build即可生成带icon的exe,根目录下不能存在多个syso文件,否则build会报错。

跨平台编译(交叉编译)

  • Mac下编译Linux, Windows平台的64位可执行程序:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build test.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go
  • Linux下编译Mac, Windows平台的64位可执行程序:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build test.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go
  • Windows下编译Mac, Linux平台的64位可执行程序:
SET CGO_ENABLED=0
SET GOOS=darwin3
SET GOARCH=amd64
go build test.go

SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build test.go

GOOS:目标可执行程序运行操作系统,支持 darwin,freebsd,linux,windows
GOARCH:目标可执行程序操作系统构架,包括 386,amd64,arm

代码

如何读取及使用命令行参数

main函数不能使用参数。
命令行参数不像c#或者java是通过main(args[])这样来传递

退出当前进程

import "os"
os.Exit(0)

解析文件路径

使用path或者path/filepath包来对路径进行解析。path/filepath支持跨平台,所以推荐使用这个。

import "path/filepath"
// Split 将路径分解成两个字符串:路径和名称
// 其中name带后缀。
path, name := filepath.Split(file)
// Ext 获取文件后缀名(如果有),包含点号,如“.txt”
ext := filepath.Ext(file)
// 获取不带后缀名的文件名。包本身不带,用strings.TrimSuffix方法把后缀清除掉,
filenameWithoutExt := strings.TrimSuffix(name, ext)

获取时间

import "time"
//返回一个Time结构体
t := time.Now()
//utc时间戳,纳秒(毫秒的1/1e6)
t.UnixNano()
//utc时间戳,秒
t.Unix()

遍历目录

//此方法会遍历目录及子目录
filepath.Walk(dirpath, func(filename string, f os.FileInfo, err error) error {
    if err != nil {
        return err
    }
    if f.IsDir() {
        log.Println(filename, "是文件夹")
    } else {
        log.Println(filename)
    }
    return nil
})

如果只要遍历当前目录,可以使用io/ioutil

dir, err := ioutil.ReadDir(dirPth)
for _, fi := range dir {
    if fi.IsDir() { // 目录。这里可以进行递归

    } else {
        // 文件
    }
}

控制多线程数量

go本身支持并发编程,通过runtime.GOMAXPROCS(n)可以设置并发数,版本1.5以后默认开启并发,并发数与逻辑CPU数相同。
在调用方法前用关键字go即可

如果调用了外部程序,在等待外部程序返回的时候,go会把CPU资源给别的协程使用,此时靠go的协程控制,可能会启用一堆的外部程序

package main
import (
    "fmt"
    "os/exec"
    "runtime"
)
func main(){
    //设置协程最大数为4
    runtime.GOMAXPROCS(4)
    //并发100个,执行run()来启动外部程序
    //此处本来希望通过go控制,最多只有4个外部程序被调用。
    //但是实际情况是,在等待外部程序返回的时候,go并没有阻塞协程,会继续调用run(),导致同时100个out.exe被启动
    for i := 0; i < 100; i++ {
        go run();
    }
}
func run(){
    //新建一个命令行 out.exe args1,此处假设程序需要运行30秒后才退出
    cmd := exec.Command("out.exe", "args1")
    //执行命令行并等待返回
    cmd.Run()
}

等待所有线程退出

package main

import "fmt"
import "time"
import "sync"

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            time.Sleep(1 * time.Second)
            fmt.Println(i)
        }(i)
    }
    wg.Wait() // 等待
    fmt.Println("main exist")
}

各种包

日志

简单日志可以使用log包进行打印

import "log"
//设置日志打印的一些项目,这里指要在日志中包含日期和毫秒
log.SetFlags(log.Ldate | log.Lmicroseconds)
log.Println("这是一条日志")

执行外部程序

import "os/exec"
// 创建一个cmd命令,此时命令还没有执行
cmd := exec.Command("exe file path", args1,args2)
// 执行方式1。Run其实就是Start后再Wait
cmd.Run()
// 执行方式2。执行命令后立刻返回
cmd.Start()
// 执行方式3。执行命令,并等待外部程序退出后获得输出信息
output := cmd.Output()
log.Printf("%s",output)
Comments are closed.