第 27 期 2019-01-10 go mod 源码阅读 part 2

观看视频

分享者

杨文

Go 标准包阅读

基于 Go 1.11.5

学到的内容

1. mf := new(modfile.File)

2. lineno++ 感觉是无用的代码?

dep.go 中 ParseGopkgLock 方法第48行有用到 lineno ,会打印出 strconv.Unquote 解析错误的文件名和行号

if len(val) >= 2 && val[0] == '"' && val[len(val)-1] == '"' {
    q, err := strconv.Unquote(val) // Go unquoting, but close enough for now
    if err != nil {
        return nil, fmt.Errorf("%s:%d: invalid quoted string: %v", file, lineno, err)
    }
    val = q
}

其他几个文件可能是为了保持一致,或者为了将来输出错误信息特意保留的。其他文件里面的 lineno 没有地方引用,大家在阅读代码时会产生困惑,建议用空白符_来替代。

3. 判断外部网络是否可用

if runtime.GOOS == "nacl" || runtime.GOOS == "js" {
	t.Skipf("skipping test: no external network on %s", runtime.GOOS)
}

runtime.GOOS返回程序所在的操作系统名

src\runtime\extern.go

// GOOS is the running program's operating system target:
// one of darwin, freebsd, linux, and so on.
const GOOS string = sys.GOOS

Native Client(NACL) 是一种允许在浏览器中运行 native compiled code 的技术,允许开发者运用自己熟悉的语言来开发web应用,而不只是JavaScript,目前 NativeClient 技术只能应用于google自己的chrome中。
js 是指 Webassembly 技术,是在新版本1.11中才支持的,最新版本的浏览器可以支持。 NACL 和 JS 都不是真正的操作系统,不提供外部网络功能。

4.旧版模块管理配置转换为modfile

读取当前目录下旧版模块管理配置文件,从 Converters 中根据配置文件名去获取转换方法。

src\cmd\go\internal\modconv\convert.go

// ConvertLegacyConfig converts legacy config to modfile.
// The file argument is slash-delimited.
func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error {
    i := strings.LastIndex(file, "/")
    j := -2
    if i >= 0 {
        j = strings.LastIndex(file[:i], "/")
    }
    convert := Converters[file[i+1:]]
    if convert == nil && j != -2 {
        convert = Converters[file[j+1:]]
    }
    if convert == nil {
        return fmt.Errorf("unknown legacy config file %s", file)
    }
    mf, err := convert(file, data)
    if err != nil {
        return fmt.Errorf("parsing %s: %v", file, err)
    }
...
}

src\cmd\go\internal\modconv\modconv.go

var Converters = map[string]func(string, []byte) (*modfile.File, error){
    "GLOCKFILE":          ParseGLOCKFILE,
    "Godeps/Godeps.json": ParseGodepsJSON,
    "Gopkg.lock":         ParseGopkgLock,
    "dependencies.tsv":   ParseDependenciesTSV,
    "glide.lock":         ParseGlideLock,
    "vendor.conf":        ParseVendorConf,
    "vendor.yml":         ParseVendorYML,
    "vendor/manifest":    ParseVendorManifest,
    "vendor/vendor.json": ParseVendorJSON,
}

目前go语言是使用map对象来存储旧配置文件和方法的映射关系这种设计思路的。@mai提出还有一种设计思路是抽象一个接口,各种配置管理来实现该接口。

参考

1.Google Native Client
2.NaCl and networking
3.Go 1.11 正式发布 支持模块和WebAssembly
4.WebAssembly 现状与实战