go学习笔记(一)

2022/7/4 23:24:10

本文主要是介绍go学习笔记(一),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

安装

语言环境

可参考: https://www.runoob.com/go/go-environment.html

安装包下载地址为:https://golang.org/dl/。

如果打不开可以使用这个地址:https://golang.google.cn/dl/。

验证

go version

集成环境

推荐:vscode , goLand

vscode安装插件支持

 

 

 

hello,world

新建项目文件夹,go-demo

mkdir go-demo
cd go-demo

编写第一个程序

Go 源文件总是用全小写字母形式的短小单词命名,并且以.go 扩展名结尾

如果要在源文件的名字中使用多个单词,我们通常直接是将多个单词连接起来作为源文件名,而不是使用其他分隔符,比如下划线。也就是说,我们通常使用 helloworld.go 作为文件名而不是 hello_world.go。因为下划线这种分隔符,在 Go 源文件命名中有特殊作用!

touch main.go
package main

import "fmt"

func main() {
    fmt.Println("hello, world")
}

编译,运行

go build ./main.go
./main

示例代码结构

定义了 Go 中的一个包 package。包是 Go 语言的基本组成单元,通常使用单个的小写单词命名,一个 Go 程序本质上就是一组包的集合。所有 Go 代码都有自己隶属的包,在这里我们的“hello,world”示例的所有代码都在一个名为 main 的包中。main 包在 Go 中是一个特殊的包,整个 Go 程序中仅允许存在一个名为 main 的包。

package main

main 包中的主要代码是一个名为 main 的函数:

func main() {   fmt.Println("hello,world") }

这里的 main 函数会比较特殊:当你运行一个可执行的 Go 程序的时候,所有的代码都会从这个入口函数开始运行。这段代码的第一行声明了一个名为 main 的、没有任何参数和返回值的函数。如果某天你需要给函数声明参数的话,那么就必须把它们放置在圆括号 () 中。

另外,那对花括号{}被用来标记函数体,Go 要求所有的函数体都要被花括号包裹起来。按照惯例,我们推荐把左花括号与函数声明置于同一行并以空格分隔。

main 函数体中之所以可以调用 fmt 包的 Println 函数,还有最后一个原因,那就是 Println 函数名的首字母是大写的。在 Go 语言中,只有首字母为大写的标识符才是导出的(Exported),才能对包外的代码可见;如果首字母是小写的,那么就说明这个标识符仅限于在声明它的包内可见

在 Go 语言中,main 包是不可以像标准库 fmt 包那样被导入(Import)的,如果导入 main 包,在代码编译阶段你会收到一个 Go 编译器错误:import “xx/main” is a program, not an importable package。

我们传入的字符串也就是我们执行程序后在终端的标准输出上看到的字符串。这种“所见即所得”得益于 Go 源码文件本身采用的是 Unicode 字符集,而且用的是 UTF-8 标准的字符编码方式,这与编译后的程序所运行的环境所使用的字符集和字符编码方式是一致的。

Go 语言的正式语法规范是使用分号“;”来做结尾标识符的。那为什么我们很少在 Go 代码中使用和看到分号呢?这是因为,大多数分号都是可选的,常常被省略,不过在源码编译时,Go 编译器会自动插入这些被省略的分号。加上分号也是完全合法的,是可以直接通过 Go 编译器编译并正常运行的。不过,gofmt 在按约定格式化代码时,会自动删除这些被我们手工加入的分号的。

自动格式化 fmt

Go 语言内置了一套 Go 社区约定俗称的代码风格,并随安装包提供了一个名为 Gofmt 的工具,这个工具可以帮助你将代码自动格式化为约定的风格。

Gofmt 是 Go 语言在解决规模化(scale)问题上的一个最佳实践,并成为了 Go 语言吸引其他语言开发者的一大卖点。很多其他主流语言也在效仿 Go 语言推出自己的 format 工具,比如:Java formatter、Clang formatter、Dartfmt 等。因此,作为 Go 开发人员,请在提交你的代码前使用 Gofmt 格式化你的 Go 源码。

go fmt ./main.go

编译

Go 是一种编译型语言,这意味着只有你编译完 Go 程序之后,才可以将生成的可执行文件交付于其他人,并运行在没有安装 Go 的环境中。

go build main.go

Go 也借鉴了动态语言的一些对开发者体验较好的特性,比如基于源码文件的直接执行,Go 提供了 run 命令可以直接运行 Go 源码文件,比如我们也可以使用下面命令直接基于 main.go 运行:

go run main.go

像 go run 这类命令更多用于开发调试阶段,真正的交付成果还是需要使用 go build 命令构建的。

复杂项目下 Go 程序的编译

越贴近真实的生产环境,也就意味着项目规模越大、协同人员越多,项目的依赖和依赖的版本都会变得复杂。

mkdir hellomodule
cd hellomodule
touch main.go
package main

import (
  "github.com/valyala/fasthttp"
  "go.uber.org/zap"
)

var logger *zap.Logger

func init() {
  logger, _ = zap.NewProduction()
}

func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
  logger.Info("hello, go module", zap.ByteString("uri", ctx.RequestURI()))
}

func main() {
  fasthttp.ListenAndServe(":8081", fastHTTPHandler)
}

Go module 

Go module 构建模式是在 Go 1.11 版本正式引入的,为的是彻底解决 Go 项目复杂版本依赖的问题,在 Go 1.16 版本中,Go module 已经成为了 Go 默认的包依赖管理机制和 Go 源码构建机制。

Go Module 的核心是一个名为 go.mod 的文件,在这个文件中存储了这个 module 对第三方依赖的全部信息。接下来,我们就通过下面命令为“hello,module”这个示例程序添加 go.mod 文件:

go mod init github.com/wanghaokun/go-demo/hellomodule

go mod init 命令的执行结果是在当前目录下生成了一个 go.mod 文件

一个 module 就是一个包的集合,这些包和 module 一起打版本、发布和分发。go.mod 所在的目录被我们称为它声明的 module 的根目录。

第一行内容是用于声明 module 路径(module path)的。而且,module 隐含了一个命名空间的概念,module 下每个包的导入路径都是由 module path 和包所在子目录的名字结合在一起构成。

go 1.18 是一个 Go 版本指示符,用于表示这个 module 是在某个特定的 Go 版本的 module 语义的基础上编写的。

go mod tidy

使用 go mod tidy 命令,让 Go 工具自动添加 源码依赖 fasthttp 和 zap 两个第三方包
go mod tidy

国内运行,可能在存在引入第三方包时,出现加载超时的情况

修改为国内源地址

go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/
go env|grep GOPROXY

go.mod 已经记录了 hellomodule 直接依赖的包的信息。不仅如此,hellomodule 目录下还多了一个名为 go.sum 的文件,这个文件记录了 hellomodule 的直接依赖和间接依赖包的相关版本的 hash 值,用来校验本地包的真实性。在构建的时候,如果本地依赖包的 hash 值与 go.sum 文件中记录的不一致,就会被拒绝构建。

有了 go.mod 以及 hellomodule 依赖的包版本信息后,我们再来执行构建:

go build main.go
./main

新起一个窗口,访问

curl localhost:8080/foo/bar

查看go输出

这下,我们的“ hellomodule”程序可算创建成功了。我们也看到使用 Go Module 的构建模式,go build 完全可以承担其构建规模较大、依赖复杂的 Go 项目的重任。

 



这篇关于go学习笔记(一)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程