Go语言

维基百科,自由的百科全书
(重定向自Golang
跳转到导航 跳转到搜索
Go
File:Go Logo Blue.svg
编程范型编译型可平行化结构化指令式
设计者罗伯特·格瑞史莫英语Robert Griesemer
罗勃·派克
肯·汤普逊
实现者Google
发行时间2009年11月10日,​16年前​(2009-11-10
当前版本
    Module:EditAtWikidata第29行Lua错误:attempt to index field 'wikibase' (a nil value)
    操作系统LinuxmacOSFreeBSDWindows
    许可证BSD
    文件扩展名.go
    网站https://go.dev/
    https://golang.google.cn/[1]
    主要实现产品
    gc (8g,6g,5g),gccgo
    受影响于
    COberonLimboNewsqueak[2]
    File:Golang.png
    Gopher(囊鼠科),Go的吉祥物

    Go(又称Golang[3])是Google开发的一种静态强类型编译型并发型,并具有垃圾回收功能的编程语言

    罗伯特·格瑞史莫英语Robert Griesemer罗勃·派克肯·汤普逊于2007年9月开始设计Go,[2]稍后伊恩·兰斯·泰勒(Ian Lance Taylor)、拉斯·考克斯(Russ Cox)加入项目。Go于2009年11月正式宣布推出,成为开放源代码项目,支持LinuxmacOSWindows等操作系统。[4]

    在2009年与2016年,Go在TIOBE指数中被列选为最佳语言。[5][6]

    目前,Go每半年发布一个二级版本(即从a.x升级到a.y)。

    描述[编辑]

    Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。Go的并行计算模型是以东尼·霍尔通信顺序进程(CSP)为基础,采取类似模型的其他语言包括OccamLimbo[2],Go也具有这个模型的特征,比如通道传输。通过goroutine和通道等并行构造可以建造线程池管道[7]。在Go 1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分函数。

    与C++相比,Go并不包括如枚举异常处理继承泛型(此功能在Go 1.18版本中加入)、断言虚函数等功能,但增加了切片(Slice)类型、并发、管道、垃圾回收接口等特性的语言级支持[2]。对于断言的存在,则持负面态度,同时也为自己不提供类型继承来辩护。

    不同于Java,Go原生提供了关联数组(也称为哈希表(Hashes)或字典(Dictionaries))。

    批评[编辑]

    尽管 Go 的官方与支持者对于语言中不使用泛型异常处理有着大量辩解说词,但批评声也从未停过。在发表 Go 语言 2.0 的草案时,官方称没有泛型异常处理模块对于 Go 发展造成很大的阻碍[8],等同承认 Go 没有这些特色是设计错误。

    Go 的垃圾回收机制一直被人诟病,直到 1.8 版本垃圾回收的功能才较为稳定。然而尽管如此,Go 的垃圾回收还是远远落后 JVM 的 G1 和 ZGC。Discord 的研发团队在2020年初甚至发表一篇博客,宣布把其中一个服务从 Go 转移至 Rust,理由是 Go 的垃圾回收会导致每2分钟出现一次卡顿,并且 Discord 研发团队测试了 Go 语言的1.8、1.9、1.10版本这个问题都没有改善[9]

    历史[编辑]

    2007年,Google设计Go,目的在于提高在多核、网络机器(networked machines)、大型代码库(codebases)的情况下的开发效率。[10]当时在Google,设计师们想要解决其他语言使用中的缺点,但是仍保留他们的优点。[11]

    设计师们主要受他们之间流传的“不要像C++”启发。[13][14][15]

    Go于2009年11月正式宣布推出,[16]版本1.0在2012年3月发布。[17][18]之后,Go广泛应用于Google的产品[19]以及许多其他组织和开源项目。

    在2016年11月,Go(一种无衬线体)和Go Mono 字体(一种等宽字体)分别由设计师查尔斯·比格洛英语Charles Bigelow克莉丝·荷姆斯英语Kris Holmes发布。两种字体均采用了WGL4英语WGL4,并且依照着 DIN 1450 标准,可清晰地使用了 large x-height 和 letterforms 。[20][21]

    在2018年8月,原生的图标更换了。待描述完整 然而,Gopher mascot 仍旧命相同的名字。[22]

    在2018年8月,Go的主要贡献者发布了两个关于语言新功能的“草稿设计——泛型异常处理,同时寻求Go用户的反馈。[23][24]Go 由于在1.x时,缺少对泛型编程的支持和冗长的异常处理而备受批评。

    版本历史[编辑]

    Go 1 保证语言规范[25]和标准库的主要部分兼容。直到目前的 Go 1.25 发布[26],所有版本都履行了这个承诺。 每个主要的 Go 发布版本会受到支持,直到出现两个新的主要版本为止。[27]

    Release Status Release date Maintenance end
    停止支持: go1 停止支持: End-of-Life 2012-03-28 2013-12-01
    停止支持: go1.1 停止支持: End-of-Life 2013-05-13 2014-06-18
    停止支持: go1.2 停止支持: End-of-Life 2013-12-01 2014-12-10
    停止支持: go1.3 停止支持: End-of-Life 2014-06-18 2015-08-19
    停止支持: go1.4 停止支持: End-of-Life 2014-12-10 2016-02-17
    停止支持: go1.5 停止支持: End-of-Life 2015-08-19 2016-08-15
    停止支持: go1.6 停止支持: End-of-Life 2016-02-17 2017-02-16
    停止支持: go1.7 停止支持: End-of-Life 2016-08-15 2017-08-24
    停止支持: go1.8 停止支持: End-of-Life 2017-02-16 2018-02-16
    停止支持: go1.9 停止支持: End-of-Life 2017-08-24 2018-08-24
    停止支持: go1.10 停止支持: End-of-Life 2018-02-16 2019-02-25
    停止支持: go1.11 停止支持: End-of-Life 2018-08-24 2019-09-03
    停止支持: go1.12 停止支持: End-of-Life 2019-02-25 2020-02-25
    停止支持: go1.13 停止支持: End-of-Life 2019-09-03 2020-08-11
    停止支持: go1.14 停止支持: End-of-Life 2020-02-25 2021-02-16
    停止支持: go1.15 停止支持: End-of-Life 2020-08-11 2021-08-16
    停止支持: go1.16 停止支持: End-of-Life 2021-02-16 2022-03-15
    停止支持: go1.17 停止支持: End-of-Life 2021-08-16 2022-08-02
    停止支持: go1.18 停止支持: End-of-Life 2022-03-15 2023-02-01
    停止支持: go1.19 停止支持: End-of-Life 2022-08-02 2023-08-08
    停止支持: go1.20 停止支持: End-of-Life 2023-02-01 2024-02-06
    停止支持: go1.21 停止支持: End-of-Life 2023-08-08 2024-08-13
    停止支持: go1.22 停止支持: End-of-Life 2024-02-06 2025-02-11
    停止支持: go1.23 停止支持: End-of-Life 2024-08-13 2025-08-12
    停止支持: go1.24 停止支持: End-of-Life 2025-02-11 2026-02-04
    支持中: go1.25 支持中: Maintenance 2025-08-12 Q3 2026
    最新版本: go1.26 最新版本: Current 2026-02-10 Q1 2027
    格式:
    停止支持
    支持中
    最新版本
    最新预览
    从未发布


    代码示例[编辑]

    Hello World[编辑]

    下面是用Go写成的Hello World程序:

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("Hello, World")
    }
    

    HTTP网页服务器[编辑]

    透过Go仅需几行代码就完成HTTP网页服务器的实现:

    package main
    
    import (
        "io"
        "net/http"
    )
    
    func hello(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Hello world!")
    }
    
    func main() {
        http.HandleFunc("/", hello)
        http.ListenAndServe(":8000", nil)
    }
    

    Echo命令程序[编辑]

    下面的例子说明了怎样用Go去实现一个像Unix中的Echo命令程序[28]

    package main
    
    import (
        "os"
        "flag"
    )
    
    var omitNewline = flag.Bool("n", false, "don't print final newline")
    
    const (
        Space   = " "
        Newline = "\n"
    )
    
    func main() {
        flag.Parse() // Scans the arg list and sets up flags
        var s string = ""
        for i := 0; i < flag.NArg(); i++ {
            if i > 0 {
                s += Space
            }
            s += flag.Arg(i)
        }
        if !*omitNewline {
            s += Newline
        }
        os.Stdout.WriteString(s)
    }
    

    语言特征[编辑]

    撰写风格[编辑]

    Go有定义如下的撰写风格:

    1. 每行程序结束后不需要撰写分号;
    2. 大括号{不能够换行放置。
    3. if判断式和for循环不需要以小括号包覆起来。
    4. 使用 tab 做排版

    除了第二点外(换行会产生编译错误),在不符合上述规定时,仍旧可以编译,但使用了内置gofmt工具后,会自动整理代码,使之符合规定的撰写风格。

    项目架构[编辑]

    module[编辑]

    Go 采用 module 的概念(于 go1.11才开始激活[29],旧版本请参阅工作区),每个项目都是一个 module ,而每个 module 底下会有个 go.mod 的文件,来管理该 module 所引用的外部库、开发版本……等等。

    一个 module 的文件夹目录可能如下

    go.mod
     hello/
         hello.go                
     outyet/
         main.go                 
         main_test.go           # 測試用的程式
     stringutil/
         reverse.go             
         reverse_test.go        #  測試用的程式
     bmp/
         reader.go              
         writer.go               

    然后 go.mod 的内容可能为

    module example.org/go-mod-sample
    
    go 1.11
    
    require (
    	github.com/golang/example v0.0.0-20220412213650-2e68773dfca0 
    	golang.org/x/image v0.1.0 
    )

    工作区[编辑]

    Go的工作区英语Workspace位于GOPATH,其目录结构如下[30]

    src
    pkg
    bin

    三个目录的用途分别为

    目录 用途
    src 引用的外部
    pkg 编译时,生成的对象文件英语Object file
    bin 编译后的程序

    举例来说,整个项目目录可能会如下:

    bin/
        hello                          # 生成的執行檔
        outyet                         # 生成的執行檔
    pkg/
        linux_amd64/
            github.com/golang/example/
                stringutil.a           # 編譯時,生成的對象檔案
    src/
        github.com/golang/example/
            .git/                      # 外部 Git 庫的詮釋資料
     hello/
         hello.go               # Git 庫的程式碼
     outyet/
         main.go                # Git 庫的程式碼
         main_test.go           # Git 庫的程式碼(測試用的程式)
     stringutil/
         reverse.go             # Git 庫的程式碼
         reverse_test.go        # Git 庫的程式碼(測試用的程式)
        golang.org/x/image/
            .git/                      # 外部 Git 庫的詮釋資料
     bmp/
         reader.go              # Git 庫的程式碼
         writer.go              # Git 庫的程式碼
    
    

    轻型协程[编辑]

    Go的主要特色在于易于使用的并行设计,叫做Goroutine,透过Goroutine能够让程序以异步的方式执行,而不需要担心一个函数导致程序中断,因此Go也非常地适合网络服务。假设有个程序,里面有两个函数:

    func main() {
        // 假設 loop 是一個會重複執行十次的迴圈函式。
        // 迴圈執行完畢才會往下執行。
        loop()
        // 執行另一個迴圈。
        loop()
    }
    

    这个时候透过Go让其中一个函数同步执行,如此就不需要等待该函数执行完后才能执行下一个函数。

    func main() {
        // 透過 `go`,我們可以把這個函式同步執行,
        // 如此一來這個函式就不會阻塞主程式的執行。
        go loop()
        // 執行另一個迴圈。
        loop()
    }
    

    Goroutine是类似线程的概念,属于纤程(区别于协程线程)。线程属于系统层面,通常来说建立一个新的线程会消耗较多的资源且管理不易;而协程的主要作用是提供在一个线程内的并发性,却不能利用多个处理器线程。而 Goroutine就像轻量级的线程,一个Go程序可以执行超过数万个 Goroutine[31],并且这些性能都是原生级的,随时都能够关闭、结束,且运行在多个处理器线程上。一个核心里面可以有多个Goroutine,透过GOMAXPROCS参数你能够限制Gorotuine可以占用几个系统线程来避免失控。

    在内置的官方包中也不时能够看见Goroutine的应用,像是net/http中用来监听网络服务的函数实际上是建立一个不断执行循环的Goroutine;同时搭配了epoll 等IO多路复用机制维护Goroutine的事件循环

    编译器[编辑]

    当前有两个Go编译器分支,分别为官方编译器gc和gccgo。官方编译器在初期使用C写成,后用Go重写从而实现自举[32]。Gccgo是一个使用标准GCC作为后端的Go编译器[33]

    官方编译器支持跨平台编译(但不支持CGO),允许将源代码编译为可在目标系统、架构上执行的二进制文件。

    应用[编辑]

    由于go的原生跨平台,以及大量的官方库,被用于大量开源程序,例如:dockerSyncthingipfsHugocaddy以太坊V2RayGiteaTiDB

    参考文献[编辑]

    1. ^ Golang.google.cn 上线_Google黑板报_新浪博客. [2020-09-14]. (原始内容存档于2021-08-14). 
    2. ^ 2.0 2.1 2.2 2.3 Language Design FAQ. [2009-11-12]. (原始内容存档于2013-01-02). 
    3. ^ Google-go-language. [2018-05-07]. (原始内容存档于2020-11-28). 
    4. ^ Installing Go. [2009-11-12]. (原始内容存档于2012-03-20). 
    5. ^ Go 首次冲进前八!曾两次夺得年度编程语言,也曾跌至百名开外 | TIOBE 2 月榜单发布_排名_Top_变化. www.sohu.com. 
    6. ^ 存档副本. [2018-09-17]. (原始内容存档于2018-09-17). 
    7. ^ Go Concurrency Patterns. golang.org. [2020-05-07]. (原始内容存档于2021-02-05). 
    8. ^ Go 2 Draft Designs. [2021-03-15]. (原始内容存档于2021-01-26). 
    9. ^ Why Discord is switching from Go to Rust. [2021-03-15]. (原始内容存档于2022-05-11). 
    10. ^ Go at Google: Language Design in the Service of Software Engineering. [2018-10-08]. (原始内容存档于2021-01-25). 
    11. ^ Pike, Rob. Another Go at Language Design. Stanford EE Computer Systems Colloquium. Stanford University. 2010-04-28 [2020-01-14]. (原始内容存档于2014-06-12).  Video available页面存档备份,存于互联网档案馆).
    12. ^ Frequently Asked Questions (FAQ) - The Go Programming Language. golang.org. [2016-02-26]. (原始内容存档于2017-02-25). 
    13. ^ Andrew Binstock. Dr. Dobb's: Interview with Ken Thompson. 2011-05-18 [2014-02-07]. (原始内容存档于2014-03-13). 
    14. ^ Pike, Rob. Less is exponentially more. 2012 [2020-01-14]. (原始内容存档于2016-03-21). 
    15. ^ Robert Griesemer. The Evolution of Go. 2015 [2020-01-14]. (原始内容存档于2017-01-16). 
    16. ^ Griesemer, Robert; Pike, Rob; Thompson, Ken; Taylor, Ian; Cox, Russ; Kim, Jini; Langley, Adam. Hey! Ho! Let's Go!. Google Open Source. Google. [2018-05-17]. (原始内容存档于2021-01-26). 
    17. ^ Shankland, Stephen. Google's Go language turns one, wins a spot at YouTube: The lower-level programming language has matured enough to sport the 1.0 version number. And it's being used for real work at Google.. News. CNet (CBS Interactive Inc). March 30, 2012 [2017-08-06]. (原始内容存档于2020-11-25). Google has released version 1 of its Go programming language, an ambitious attempt to improve upon giants of the lower-level programming world such as C and C++. 
    18. ^ Release History. [2014-12-11]. (原始内容存档于2017-02-17). 
    19. ^ Go FAQ: Is Google using Go internally?. [2013-03-09]. (原始内容存档于2017-02-25). 
    20. ^ Go fonts – The Go Blog. Go. 2016-11-16 [2019-03-12]. (原始内容存档于2019-07-31). 
    21. ^ Go Font TTFs. GitHub. Google. [2019-04-02]. (原始内容存档于2019-07-31). 
    22. ^ Go's New Brand – The Go Blog. blog.golang.org. [2018-11-09]. (原始内容存档于2020-11-25). 
    23. ^ Go 2 Draft Designs. [2018-09-12]. (原始内容存档于2021-01-26). 
    24. ^ The Go Blog: Go 2 Draft Designs. 2018-08-28 [2020-01-14]. (原始内容存档于2021-01-31). 
    25. ^ Go 1 and the Future of Go Programs. golang.org. [2023-04-12]. (原始内容存档于2017-10-02). 
    26. ^ Go 1.20 Release Notes. go.dev. [2023-04-12]. (原始内容存档于2023-05-30). 
    27. ^ Release History. golang.org. [2023-04-12]. (原始内容存档于2017-02-17). 
    28. ^ 存档副本. [2009-11-20]. (原始内容存档于2013-07-08). 
    29. ^ Go 1.11 Release Notes. The Go Programming Language. [2022-11-18]. (原始内容存档于2023-01-03). 
    30. ^ How to Write Go Code. The Go Programming Language. [2017-11-15]. (原始内容存档于2019-02-13) (English). 
    31. ^ Max number of goroutines. stackoverflow.com. [2017-03-20]. (原始内容存档于2020-11-25). 
    32. ^ Google公布实现Go 1.5自举的计划. [2015-06-09]. (原始内容存档于2018-08-07). 
    33. ^ Go FAQ: Implementation. [2009-11-12]. (原始内容存档于2013-01-02). 

    外部链接[编辑]