300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > go语言入门教程01-go工具+go语法+go module

go语言入门教程01-go工具+go语法+go module

时间:2021-07-24 21:21:57

相关推荐

go语言入门教程01-go工具+go语法+go module

文章目录

go教程go 简介go 安装go 常用命令build 和 run 命令fmt 和 doc 命令install 命令env 命令get 命令go package包的基本概念包导入包管理工具GOROOT 和GOPATH区别Vendor 机制引入Go Modules启用 go module 功能使用 go module 功能go语法变量定义普通变量结构体和接口字符串数组切片map链表list流程控制循环函数异常处理

go教程

go 简介

Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。

Go是从末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于11月开源,在早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。

相关网站:

go官网:/pkg/

go依赖包搜索:/

go 安装

安装包下载地址为:/dl/。

window安装目录默认为:c:/go,bin目录自动指向bin目录。

linux解压tgz包,将bin目录添加到PATH变量中,假设go解压在/opt/go目录下

cat << 'EOF' >> ~/.bash_profilePATH=$PATH:/opt/go/binexport PATHEOF

测试go是否正常安装

C:\Users\GVT>go versiongo version go1.14.2 windows/amd64

go 常用命令

直接在终端中输入 go help 即可显示所有的 go 命令以及相应命令功能简介,主要有下面这些:

build: 编译包和依赖clean: 移除对象文件doc: 显示包或者符号的文档env: 打印go的环境信息bug: 启动错误报告fix: 运行go tool fixfmt: 运行gofmt进行格式化generate: 从processing source生成go文件get: 下载并安装包和依赖install: 编译并安装包和依赖list: 列出包run: 编译并运行go程序test: 运行测试tool: 运行go提供的工具version: 显示go的版本vet: 运行go tool vet

命令的使用方式为: go command [args], 除此之外,可以使用go help 来显示指定命令的更多帮助信息。

在运行 go help 时,不仅仅打印了这些命令的基本信息,还给出了一些概念的帮助信息:

c: Go和c的相互调用buildmode: 构建模式的描述filetype: 文件类型gopath: GOPATH环境变量environment: 环境变量importpath: 导入路径语法packages: 包列表的描述testflag: 测试符号描述testfunc: 测试函数描述

同样使用 go help 来查看这些概念的的信息。

build 和 run 命令

就像其他静态类型语言一样,要执行 go 程序,需要先编译,然后在执行产生的可执行文件。go build 命令就是用来编译 go程序生成可执行文件的。但并不是所以的 go 程序都可以编译生成可执行文件的, 要生成可执行文件,go程序需要满足两个条件:

该go程序需要属于main包在main包中必须还得包含main函数

也就是说go程序的入口就是 main.main, 即main包下的main函数,例子(hello.go):

cat <<EOF > hello.gopackage mainimport "fmt"func main(){fmt.Println("Hello World")}EOF

编译hello.go,然后运行可执行程序:

go build hello.go

当前目录下生成了hello.exe,运行

GVT@DESKTOP-V14R68B MINGW64 ~/go$ ./hello.exeHello World

而 go run 命令可以将上面两步并为一步执行(不会产生中间文件)。

$ go run hello.goHello World!

上面两个命令都是在开发中非常常用的。

此外 go clean 命令,可以用于将清除产生的可执行程序:

$ go clean # 不加参数,可以删除当前目录下的所有可执行文件$ go clean sourcefile.go # 会删除对应的可执行文件

fmt 和 doc 命令

go 语言有一个褒贬不一的特性,就是对格式的要求很严格,我是很喜欢这个特性的,因为可以保持代码的清晰一致,编译组合开发,并且go还提供了一个非常强大的工具来格式化代码,它就是 go fmt sourcefile.go, 不过通常其实不需要我们手动调用,各种编辑器都可以帮助我们自动完成格式化。

go doc 命令可以方便我们快速查看包文档,go doc package 命令将会在终端中打印出指定 package 的文档。

如查看fmt文档

go doc fmt

另外有一个与 go doc 命令相关的命令是 godoc, 可以通过它启动我们自己的文档服务器:

godoc -http=:8080

然后我们就可与在浏览器localhost:8080中查看go文档了

godoc默认不带可执行程序,生成可执行程序步骤

git clone /golang/tools /x/tools go安装目录/src新建\x\tools目录 拷贝源代码到该目录cd C:\Go\src\\x\tools\godocgo build /x/tools/cmd/godocgo install /x/tools/cmd/godoc 自动拷贝到bin目录

install 命令

用来编译和安装go程序,我们可以将它与 build 命令对比:

生成的可执行文件路径 工作目录下的bin目录下 当前目录下

可执行文件的名字 与源码所在目录同名 默认与源程序同名,可以使用-o选项指定

依赖 将依赖的包放到工作目录下的pkg文件夹下 -

env 命令

查看所有环境变量

go envgo env | grep GOROOT

修改环境变量(设置中国区代理或者阿里云代理:/goproxy/)

go env -w GOPROXY=

get 命令

go get 命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装。整个过程就像安装一个 App 一样简单。

这个命令可以动态获取远程代码包,目前支持的有 BitBucket、GitHub、Google Code 和 Launchpad。在使用 go get 命令前,需要安装与远程包匹配的代码管理工具,如 Git、SVN、HG 等,参数中需要提供一个包名。

这个命令在内部实际上分成了两步操作:第一步是下载源码包,第二步是执行 go install。下载源码包的 go 工具会自动根据不同的域名调用不同的源码工具,对应关系如下:

BitBucket (Mercurial Git)GitHub (Git)Google Code Project Hosting (Git, Mercurial, Subversion)Launchpad (Bazaar)

所以为了 go get 命令能正常工作,你必须确保安装了合适的源码管理工具,并同时把这些命令加入你的 PATH 中。其实 go get 支持自定义域名的功能。

参数介绍:

-d 只下载不安装-f 只有在你包含了 -u 参数的时候才有效,不让 -u 去验证 import 中的每一个都已经获取了,这对于本地 fork 的包特别有用-fix 在获取源码之后先运行 fix,然后再去做其他的事情-t 同时也下载需要为运行测试所需要的包-u 强制使用网络去更新包和它的依赖包-v 显示执行的命令

Go语言的代码被托管于 网站,该网站是基于 Git 代码管理工具的,很多有名的项目都在该网站托管代码。其他类似的托管网站还有 、 等。

这些网站的项目包路径都有一个共同的标准,参见下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lZFb5vnB-1589278910682)(images/1.jpg)]

图中的远程包路径是 Go语言的源码,这个路径共由 3 个部分组成:

网站域名:表示代码托管的网站,类似于电子邮件 @ 后面的服务器地址。作者或机构:表明这个项目的归属,一般为网站的用户名,如果需要找到这个作者下的所有项目,可以直接在网站上通过搜索“域名/作者”进行查看。这部分类似于电子邮件 @ 前面的部分。项目名:每个网站下的作者或机构可能会同时拥有很多的项目,图中标示的部分表示项目名称。

默认情况下,go get 可以直接使用。例如,想获取 go 的源码并编译,使用下面的命令行即可:

go get /davyxu/cellnet

获取前,请确保 GOPATH 已经设置。Go 1.8 版本之后,GOPATH 默认在用户目录的 go 文件夹下。

cellnet 只是一个网络库,并没有可执行文件,因此在 go get 操作成功后 GOPATH 下的 bin 目录下不会有任何编译好的二进制文件。

需要测试获取并编译二进制的,可以尝试下面的这个命令。当获取完成后,就会自动在 GOPATH 的 bin 目录下生成编译好的二进制文件。

go get -u /gpmgo/gopm

查看你的GOPATH/bin目录下是否生成gopm.exe,src是否有gpmgo源码。

go package

包的基本概念

Go语言的包借助了目录树的组织形式,一般包的名称就是其源文件所在目录的名称,虽然Go语言没有强制要求包名必须和其所在的目录名同名,但还是建议包名和所在目录同名,这样结构更清晰。

包可以定义在很深的目录中,包名的定义是不包括目录路径的,但是包在引用时一般使用全路径引用。比如在GOPATH/src/a/b/ 下定义一个包 c。在包 c 的源码中只需声明为package c,而不是声明为package a/b/c,但是在导入 c 包时,需要带上路径,例如import “a/b/c”。

包的习惯用法:

包名一般是小写的,使用一个简短且有意义的名称。包名一般要和所在的目录同名,也可以不同,包名中不能包含- 等特殊符号。包一般使用域名作为目录名称,这样能保证包名的唯一性,比如 GitHub 项目的包一般会放到GOPATH/src//userName/projectName 目录下。包名为 main 的包为应用程序的入口包,编译不包含 main 包的源码文件时不会得到可执行文件。

一个文件夹下的所有源码文件只能属于同一个包,同样属于同一个包的源码文件不能放在多个文件夹下。

包导入

单行导入

import "包 1 的路径"import "包 2 的路径"

多行导入

import ("包 1 的路径""包 2 的路径")

别名

package mainimport F "fmt"func main() {F.Println("C语言中文网")}

省略引用

package mainimport . "fmt"func main() {//不需要加前缀 fmt.Println("C语言中文网")}

标准的Go语言代码库中包含了大量的包,并且在安装 Go 的时候多数会自动安装到系统中。我们可以在 $GOROOT/src/pkg 目录中查看这些包。下面简单介绍一些我们开发中常用的包。

fmt

fmt 包实现了格式化的标准输入输出,这与C语言中的 printf 和 scanf 类似。其中的 fmt.Printf() 和 fmt.Println() 是开发者使用最为频繁的函数。

格式化短语派生于C语言,一些短语(%- 序列)是这样使用: %v:默认格式的值。当打印结构时,加号(%+v)会增加字段名;%#v:Go样式的值表达;%T:带有类型的 Go 样式的值表达。 io

这个包提供了原始的 I/O 操作界面。它主要的任务是对 os 包这样的原始的 I/O 进行封装,增加一些其他相关,使其具有抽象功能用在公共的接口上。bufio

bufio 包通过对 io 包的封装,提供了数据缓冲功能,能够一定程度减少大块数据读写带来的开销。

在 bufio 各个组件内部都维护了一个缓冲区,数据读写操作都直接通过缓存区进行。当发起一次读写操作时,会首先尝试从缓冲区获取数据,只有当缓冲区没有数据时,才会从数据源获取数据更新缓冲。sort

sort 包提供了用于对切片和用户定义的集合进行排序的功能。strconv

strconv 包提供了将字符串转换成基本数据类型,或者从基本数据类型转换为字符串的功能。os

os 包提供了不依赖平台的操作系统函数接口,设计像 Unix 风格,但错误处理是 go 风格,当 os 包使用时,如果失败后返回错误类型而不是错误数量。sync

sync 包实现多线程中锁机制以及其他同步互斥机制。flag

flag 包提供命令行参数的规则定义和传入参数解析的功能。绝大部分的命令行程序都需要用到这个包。encoding/json

JSON 目前广泛用做网络程序中的通信格式。encoding/json 包提供了对 JSON 的基本支持,比如从一个对象序列化为 JSON 字符串,或者从 JSON 字符串反序列化出一个具体的对象等。html/template

主要实现了 web 开发中生成 html 的 template 的一些函数。net/http

net/http 包提供 HTTP 相关服务,主要包括 http 请求、响应和 URL 的解析,以及基本的 http 客户端和扩展的 http 服务。

通过 net/http 包,只需要数行代码,即可实现一个爬虫或者一个 Web 服务器,这在传统语言中是无法想象的。reflect

reflect 包实现了运行时反射,允许程序通过抽象类型操作对象。通常用于处理静态类型 interface{} 的值,并且通过 Typeof 解析出其动态类型信息,通常会返回一个有接口类型 Type 的对象。os/exec

os/exec 包提供了执行自定义 linux 命令的相关实现。strings

strings 包主要是处理字符串的一些函数集合,包括合并、查找、分割、比较、后缀检查、索引、大小写处理等等。

strings 包与 bytes 包的函数接口功能基本一致。bytes

bytes 包提供了对字节切片进行读写操作的一系列函数。字节切片处理的函数比较多,分为基本处理函数、比较函数、后缀检查函数、索引函数、分割函数、大小写处理函数和子切片处理函数等。log

log 包主要用于在程序中输出日志。

log 包中提供了三类日志输出接口,Print、Fatal 和 Panic。

Print 是普通输出;Fatal 是在执行完 Print 后,执行 os.Exit(1);Panic 是在执行完 Print 后调用 panic() 方法。

包管理工具

除了go工具链自带的工具比如,go build 、go vet 、go get 、 go doc 等等,还有包依赖管理工具。比如 dep等等,go 1.11 1.12 还添加了 go modules 。

一直依赖go语言被人吐槽的就是包依赖管理 和 错误处理方式。 社区出现了一批包依赖管理工具。

GOROOT 和GOPATH区别

两个概念:GOROOT 和GOPATH

GOROOT: 系统环境变量,就是我们存放下载的go语言源码的地方(go的源码,不是我们写的)。GOPATH: 环境变量,我们的工作空间,包括bin、pkg、src。是存放我们写的代码以及下载的第三方代码。

依赖,分为内部依赖和外部依赖。

内部依赖:

GOPATH和GOROOT,GOROOT并不是必须要设置的,但是GOPATH必须要设置,但并不是固定不变的。本项目内部依赖就会在GOPATH 所配置的路径下去寻找,编译器如果找不到会报错。总的来说内部依赖不需要太操心。

外部依赖包:

当我们要实现一些功能的时候,不可避免的需要一些第三方包,也统称为外部依赖包。go1.5之前只支持使用GOPATH来管理外部依赖包的,对比java的maven 和gradle等 简直不太方便。

Vendor 机制引入

在go1.5release之前,我们要管理多个依赖包版本时,只能通过设置多个GOPATH,拷贝代码来解决。比如,如果两个工程都依赖了Beego,一个1.5,一个1.8,那么必须设置俩GOPATH,并且还要记得切换。

go语言原生包缺陷:

能拉取源码的平台很有限,绝大多数依赖的是

不能区分版本,以至于令开发者以最后一项包名作为版本划分

依赖 列表/关系 无法持久化到本地,需要找出所有依赖包然后一个个 go get

只能依赖本地全局仓库(GOPATH/GOROOT),无法将库放置于局部仓库($PROJECT_HOME/vendor)

简单说,就是在你项目中多了一个vendor文件夹,go会把它默认作为GOPATH。让go编译时,优先从项目源码树根目录下的vendor目录查找代码(可以理解为切了一次GOPATH),如果vendor中有,则不再去GOPATH中去查找。

社区支持vendor的包管理库有很多,官方推荐的就有15种。

用的比较多的有dep(官方)、Godep、Govendor等等

go官方的包管理工具是dep,目前来看也是用的最多的,是官方建议使用的。

官方wiki各种对比: /golang/go/wiki/PackageManagementTools

安装方式也比较简单,下载对应平台可执行文件:/golang/dep/releases,拷贝到GOROOT/bin目录

在自己工作目录下,使用 dep 初始化会报错:

$ dep initinit failed: unable to detect the containing GOPATH: /home/zhongwei/work/my_project/go is not within a known GOPATH/src

也就是说项目开发定义在GOPATH目录才能使用

不希望将新项目的目录 my_project/go 加入到 GOPATH 中,觉得非常麻烦,另外看了consul源码发现都切换到了go module,此时只好放弃dep。

Go Modules

使用 go module 管理依赖后会在项目根目录下生成两个文件 go.mod 和 go.sum。

go.mod 中会记录当前项目的所依赖,文件格式如下所示:

module /gosoon/audit-webhookgo 1.12require (/elastic/go-elasticsearch v0./gorilla/mux v1./gosoon/glog v0.0.0-0521124921-a5fbfb162a81)

go.sum记录每个依赖库的版本和哈希值,文件格式如下所示:

/elastic/go-elasticsearch v0.0.0 h1:Pd5fqOuBxKxv83b0+xOAJDAkziWYwFinWnBO0y+TZaA=/elastic/go-elasticsearch v0.0.0/go.mod h1:TkBSJBuTyFdBnrNqoPc54FN0vKf5c04IdM4zuStJ7xg=/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I=/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=/gosoon/glog v0.0.0-0521124921-a5fbfb162a81 h1:JP0LU0ajeawW2xySrbhDqtSUfVWohZ505Q4LXo+hCmg=/gosoon/glog v0.0.0-0521124921-a5fbfb162a81/go.mod h1:1e0N9vBl2wPF6qYa+JCRNIZnhxSkXkOJfD2iFw3eOfg=

启用 go module 功能

(1) go 版本 >= v1.11

(2) 设置GO111MODULE环境变量

要使用go module 首先要设置GO111MODULE=on,GO111MODULE 有三个值,off、on、auto,off 和 on 即关闭和开启,auto 则会根据当前目录下是否有 go.mod 文件来判断是否使用 modules 功能。无论使用哪种模式,module 功能默认不在 GOPATH 目录下查找依赖文件,所以使用 modules 功能时请设置好代理。

在使用 go module 时,将 GO111MODULE 全局环境变量设置为 off,在需要使用的时候再开启,避免在已有项目中意外引入 go module。

使用 go module 功能

对于新建项目使用 go module:

go mod init /作者/项目名称

构建项目

go build hello.go

首先需要使用 go mod vendor 将项目所有的依赖下载到本地 vendor 目录中然后进行编译.

如代码中添加import

package mainimport . "fmt"import "/google/uuid"func main() {Println("helloword")uuid:=uuid.New()Println(uuid)}

执行命令(自動下載到vendor目录)

F:\code\go\helloworld>go mod vendorgo: finding module for package /google/uuidgo: downloading /google/uuid v1.1.1go: found /google/uuid in /google/uuid v1.1.1

go.mod中多了一行依赖

/google/uuid v1.1.1

go.sum中多了

/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

使用 Go 的其他包管理工具 godep、govendor、glide、dep 等都避免不了翻墙的问题,Go Modules 也是一样,但在go.mod中可以使用replace将特定的库替换成其他库:

replace (/x/text v0.3.0 => /golang/text v0.3.0)

也可以使用阿里云的镜像站:

go env -w GOPROXY=/goproxy/或者设置环境变量export GOPROXY=/goproxy/

go语法

变量定义

普通变量

package mainimport "fmt"type byte int8 //定义一个新的类型bytetype byteAlias = int8 //定义一个别名指向int8 实际类型还是int8func main() {var i, k int = 10, 100var ife bool = falsei = 100j := 100.5 //新变量根据值判断类型使用:= 必须要var关键字 后续赋值还是使用=j = 100.6fmt.Print(i + k)fmt.Print(ife)fmt.Println(j)ks := &i //引用指向 改了ks就等于改了i*ks = 10fmt.Println(*ks, i)const js int = 100 //常量fmt.Println(js)const (a = iota //引用一次累加一次 第一次是0b = iota //1c = iota //2)fmt.Println(a, b, c)var an byte = 1fmt.Printf("%T\n", an) //类型是main.bytevar an1 byteAlias = 1fmt.Printf("%T\n", an1) //类型是int8}

结构体和接口

package mainimport "fmt"/**结构体类似于类*/type User struct {userName stringuserEmail stringuserSex int}/**定义接口,定义方法参数是string类型返回值是int类型*/type Phone interface {call(string) int}/**定义实现结构*/type Iphone struct {}/**Iphone实现call方法*/func (iphone Iphone) call(message string) int {fmt.Println("iphone说了:" + message)return 1}func main() {user := User{"zs", "aa@", 0}fmt.Println(user.userEmail)user1 := User{userEmail: "app@"}fmt.Println(user1.userEmail)phone := new(Iphone)phone.call("helloworld")}

字符串

package mainimport ("fmt""strings")func main() {//字符串切割str := "a_b_c"var result []string = strings.Split(str, "_")fmt.Println(result)//字符串包含fmt.Println(strings.Contains(str, "c"))//字符串在另一个字符串位置 ,下标从0开始fmt.Println(strings.Index(str, "_"))//比较字符串 相等返回0 a<b返回-1 a>b返回1fmt.Println(pare(str, "a_b"))//返回某个字符串出现次数fmt.Println(strings.Count(str, "_"))//找到最后一个匹配字符的位置fmt.Println(strings.LastIndex(str, "_"))//是否某个字符开头fmt.Println(strings.HasPrefix(str, "a_"))//是否某个字符结尾fmt.Println(strings.HasSuffix(str, "a_"))//join数组元素拼接成sep分格字符串//[长度]定义指定长度数组,...根据值确定长度var strlist = []string{"a", "b"}var strlist1 = [...]string{"a", "b"}var strlist2 [2]stringstrlist2[0] = "zs"strlist2[1] = "ls"cc := strings.Join(strlist, ",")fmt.Println(cc, strlist1)//将某个字符串替换成目标字符串多少次fmt.Println(strings.Replace(str, "_", "-", strings.Count(str, "_")))//转换大小写fmt.Println(strings.ToUpper(str), strings.ToLower(str))//去除左右空格,去掉指定字符fmt.Println(strings.TrimSpace(" a b "), strings.TrimLeft("_abc_", "_"))//截取字符串 从开始索引到结束索引,包含开头不包含结尾。fmt.Println(str[1:2])}

数组

package mainimport "fmt"func main() {var k string = "a"//初始化带值var arr = [...]string{"zs", "ls"}arr1 := []string{"zs", "ls"}arr2 := [2]string{"zs", "ls"}fmt.Println(k, arr, arr1, arr2)//只定义不初始化var arr3 [3]stringarr3[0] = "zs"//修改数组值arr3[1] = "ls"fmt.Println(arr3)//获取数组值fmt.Println(arr3[1])//获取数组长度fmt.Println(len(arr3))//循环数组for i := 0; i < len(arr3); i++ {fmt.Println(i, arr3[i])}}

切片

package mainimport "fmt"func main() {//可以声明一个未指定大小的数组来定义切片:var idList []int//定义切片numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}//追加numbers和10到一个新的切片中,bumbers本身不变idList = append(numbers, 10)fmt.Println(numbers)fmt.Println(idList)/* 创建切片 numbers1 是之前切片的两倍容量*/numbers1 := make([]int, len(numbers), (cap(numbers))*2)/* 拷贝 numbers 的内容到 numbers1 */copy(numbers1, numbers)fmt.Println(numbers1)}

map

package mainimport "fmt"func main() {//var map_variable map[key_data_type]value_data_typekvs := map[string]string{"id": "1", "name": "zs"}fmt.Println(kvs)a := 1var b int = 10for k, v := range kvs {fmt.Println(k, v)}}

链表list

package mainimport ("container/list""fmt")func main() {//列表是一种非连续的存储容器,由多个节点组成,节点通过一些变量记录彼此之间的关系,列表有多种实现方法,如单链表、双链表等。userList:=list.New()userList.PushBack("zs")userList.PushFront("ls")fmt.Println(userList.Len())for i:=userList.Front();i!=nil;i=i.Next(){fmt.Println(i.Value)}}

流程控制

package mainimport ("bufio""fmt""os")func main() {in := bufio.NewReader(os.Stdin)str, _, err := in.ReadLine()if err != nil {fmt.Println(err.Error())}if string(str) == "1" {fmt.Print("boy")} else {fmt.Println("girl")}}

循环

package mainimport "fmt"func main() {//初始化带值var arr = [...]string{"zs", "ls"}//循环数组for i := 0; i < len(arr); i++ {fmt.Println(i, arr[i])}//range类似于foreach 参数1是索引参数2是指,不需要某个值可以使用_ ,一般用于map类型for index, value := range arr {fmt.Println(index, value)}for _, value := range arr {fmt.Println(value)}//条件循环,打印1-10所有奇数i := 0for i < 10 {i++if i%2 == 0 {continue}fmt.Printf("%v ", i)}fmt.Println()i = 0LOOP:for i < 10 {i++if i%2 == 0 {goto LOOP //等价于continue,也可以在任意地方定义label 根据逻辑goto}fmt.Printf("%v ", i)}}

函数

package mainimport "fmt"//func function_name( [parameter list] ) [返回值类型] {func add(i int, j int) int {return i + j}func calc(i int, j int) (int, int) {return i + j, i - j}func main() {fmt.Println(add(100, 34))addresult, minusResult := calc(100, 34)fmt.Println(addresult, minusResult)}

异常处理

package mainimport ("errors""fmt")/**error的接口定义type error interface {Error() string}*//**一般可以在函数最后一个参数添加一个错误参数,通过errors.New创建*/func div(num1 int,num2 int) (int,error){if(num2==0){return 0,errors.New("除数不能为0")}return num1/num2,nil}/**自定义异常,比如*/type Sex struct {sex int;//性别只能为0和1}func (sex Sex) Error() string{return fmt.Sprintf("性别字段%v只能为0和1", sex.sex)}func setSex(sex Sex)(string){if(sex.sex!=1 && sex.sex !=0){return sex.Error();}return ""}func main() {result,err:=div(100,0)if(err!=nil){fmt.Println(err)}else{fmt.Println(result)}sex:=Sex{2}errorMsg:=setSex(sex)fmt.Println(errorMsg)}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。