要解决的问题

  • 复用其他人的工作
  • 不依赖二进制接口
  • 完整的类型信息保留

解决方案

编程语言基本上都有把源代码拆分成多个source library来编写的能力。 编译的时候把多个source library定义的逻辑编译成一个或者多个object文件。 把 compiler 在这个过程里扮演的角色称之为 source library linker

构成

构成 解释
source library 源代码库
object 多个 source library 一步到位合并成一个 object,或者变成多个有链接关系的 object
source library linker 一般就是编译器自身

解决方案案例

tsc

src/main.ts

import {data} from './lib' // referenced source library
import * as unique from 'uniq' // referenced static library

console.log(unique(data));

src/lib.ts

export let data = [1, 2, 2, 3, 4, 5, 5, 5, 6]

build.sh

# 用 AMD 的格式输出 object 文件
# main.ts  和 lib.ts 被链接成一个 object.js
tsc --outFile dist/object.js --module amd src/main.ts

dist/object.js

define("lib", ["require", "exports"], function (require, exports) {
    "use strict";
    exports.__esModule = true;
    exports.data = [1, 2, 2, 3, 4, 5, 5, 5, 6];
});
define("main", ["require", "exports", "lib", "uniq"], function (require, exports, lib_1, unique) {
    "use strict";
    exports.__esModule = true;
    console.log(unique(lib_1.data));
});
构成 对应
source library .ts 文件
static library CJS / AMD / ES6 Module
object 合并成 .js 文件
source library linker tsc

go

go.mod

module example.com/a/example

require github.com/thoas/go-funk v0.0.0-20181020164546-fbae87fb5b5c

main.go

package main

import (
    "example.com/a/example/lib"
    "fmt"
    "github.com/thoas/go-funk"
)

func main() {
    fmt.Println(funk.Uniq(lib.Data))
}

lib/lib.go

package lib

var Data = []int{1, 2, 2, 3, 4, 5, 5, 5, 6}

build.sh

# 因为 example.com/a/example 所以会产生 example 为名字的二进制可执行文件
go build
构成 对应
source library 包含 .go 文件的目录
static library 其他包含 .a 文件的目录
object 产生的二进制可执行文件
source library linker go