Go语言初探

概述

Go语言是2009年谷歌推出的一种速度与C/C++性能媲美的编程语言,而且更加安全、支持并行进程,不论是C/C++、PHP,还是Java,重构首选语言就是Go。
Golang

Go语言以其在高并发场景下的天然优势,已经成为今天开发分布式系统的首选语言,在云计算领域占据了无法替代的位置。如今,越来越多的项目组织都选择了Go来编写核心处理模块。在当下最热门的技术领域——区块链上,我们熟知的以太坊、SiaCoin、IPFS等都在使用Go语言开发,甚至可以大胆预测:继云计算之后,未来整个区块链行业也将是Go的天下。

安装

下载

Go提供了Linux、Mac、Windows等安装包,可以到 谷歌 下载,如果被墙也可以选择 studygolang

配置

Windows安装比较方便,直接下载msi文件,按照步骤即可。Linux、Mac下解压安装包,配置环境变量即可。如

export GOROOT=/home/`whoami`/Tools/go1.10.3.linux-amd64/go
export GOPATH=/home/`whoami`/WorkSpace/go:/home/`whoami`/HdData/tmp/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

GOROOT是Go的安装目录,为了方便可以添加到PATH中,GOPATH是WorkSpace,后面补充说明GOPATH的用法。

手动构建

HelloWorld

好像入门总是少不了HelloWorld,这里也免不了俗套

//hello.go
package main

import "fmt"

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

go的入口是main包的main函数,执行命令

go run hello.go

输出

Hello, World!

哈哈,是不是吓一跳,Go不是编译型静态语言吗?!实际上是因为go的编译速度实在太快了。
当然你也可以编译再执行

go build -o hello hello.go && ./hello

GOPATH

go build命令是编译出可执行文件,而go install是编译后并把可执行文件放到GOPATH的bin目录里,因此可以把$GOPATH/bin加入PATH中方便执行,如配置所示。

根据约定GOPATH的每一个工作目录结构如下

.
├── bin install的可执行应用路径
│   └── helloworld 可执行应用,因为$GOPATH/bin加入了PATH,可以直接执行
├── pkg 编译包时,生成的.a文件存放路径
└── src 源码路径
└── helloworld go项目,默认约定,go run,go install等命令的当前工作路径
└── hello.go

IDE构建

编辑器有很多种,你可以用windows的记事本、notepad++,也可以用gedit、vim,但业界有些同学推荐LiteIDE,而我选择了GoLand,完全取决于个人喜好,习惯了JetBrains产品,如何获得注册码请参考Intellij IDEA的使用和优化之路
GoLand

Dep构建

我们可能都听过Maven、Gradle或WebPack等,他们都是构建工具,其作用之一就是依赖管理,Go的依赖管理工具也有几种,这里简单介绍下Dep。Dep的安装方式可以参考GitHub中的安装
Dep

init

进入GOPATH目录,创建项目depdemo,并执行init命令

mkdir src/depdemo && cd src/depdemo && dep init

此时目录结构是

.
├── Gopkg.lock 类似npm的package-lock.json
├── Gopkg.toml 类似maven的pom,webapck的package.json
└── vendor 依赖存储

添加依赖

此时如果使用dep ensure -add添加依赖时会遇到异常

no dirs contained any Go code

因为检测到项目没有任何Go代码,把之前的hello.go复制到次项目即可添加依赖,如

dep ensure -add github.com/jinzhu/now

这是个时间类库,此时vendor目录及Gopkg.toml配置都会增加相应的依赖,当然你可以手动配置toml在ensure。

使用依赖

依赖添加完成,就可以在代码中引用了,人工使用Goland导入项目如下图
GoLand导入项目

代码如下

//hello.go
package main

import (
"fmt"
"github.com/jinzhu/now"
)


func main() {
fmt.Println("Hello, World!")
fmt.Println(now.BeginningOfDay())
}

执行输出

Hello, World!
2018-09-08 00:00:00 +0800 CST

Dep工具目前只有依赖管理,比如build,install等都还没有,而且init最好能生成基本的archtype比较舒服,比着maven、gradle还差老远的距离。

module

Go 1.11版本新增了moudle功能,从此可以告别GOPATH了,在1.11版本中是实验性质的功能,所以其GO111MODULE的配置是auto,意思是如果项目处于GOPATH中则使用GOPATH,但1.12版本中已经完全启用了module功能,GO111MODULE已经设置为on。

  1. 创建项目

    $ mkdir testmodule
    $ cd testmodule/
    $ go mod init testmodule
    go: creating new go.mod: module testmodule
  2. 查看go.mod

    $ cat go.mod 
    module testmodule

    go 1.12
  3. 获取依赖

    $ go get -u github.com/tidwall/gjson
    go: finding github.com/tidwall/pretty latest
    $ cat go.mod
    module testmodule

    go 1.12

    require (
    github.com/tidwall/gjson v1.2.1 // indirect
    github.com/tidwall/match v1.0.1 // indirect
    github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 // indirect
    )
  4. 查看mod的帮助

    $ go help mod
    Go mod provides access to operations on modules.

    Note that support for modules is built into all the go commands,
    not just 'go mod'. For example, day-to-day adding, removing, upgrading,
    and downgrading of dependencies should be done using 'go get'.
    See 'go help modules' for an overview of module functionality.

    Usage:

    go mod <command> [arguments]

    The commands are:

    download download modules to local cache
    edit edit go.mod from tools or scripts
    graph print module requirement graph
    init initialize new module in current directory
    tidy add missing and remove unused modules
    vendor make vendored copy of dependencies
    verify verify dependencies have expected content
    why explain why packages or modules are needed

    Use "go help mod <command>" for more information about a command.

golang.org/x类库

我们都知道由于golang.org被墙,导致golang.org/x/下的类库无法直接获取,会报类似如下异常

unrecognized import path “golang.org/x/….” (https fetch: Get https://golang.org/x/...?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
go: error loading module requirements

幸运的是在github上有存储,可以间接的获取,使用go mod edit的replace替换golang.org/x/,格式如下:

go mod edit -replace=old[@v]=new[@v]

例如

go mod edit -replace=golang.org/x/sys@v0.0.0-20190222072716-a9d3bda3a223=github.com/golang/sys@v0.0.0-20190502175342-a43fa875dd82

实际上这条命令会在go.mod添加如下记录

replace (
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 => github.com/golang/sys v0.0.0-20190502175342-a43fa875dd82
)

总结

Go作为目前非常热门的语言之一,自有其优势如:简明扼要,开发效率高;编译型语言执行速度快;有先进的并发支持模型;可以全自动地垃圾回收;自带工具强制编码风格;强大的标准库应用广泛等。

既然决定学习,必然纵向深入再横向拓展,网上无意间看到一张Go的知识图谱,与君共勉。
Go知识图谱

翟前锋 wechat
欢迎订阅我的微信公众号:zhaiqianfeng!