前言
Go 语言简洁
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。 Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。
Go 语言特色 (1)简洁、快速、安全 (2)并行、有趣、开源 (3)内存管理、v数组安全、编译迅速
Go 语言用途 Go语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。 对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。
Go 语言开发工具推荐 LiteIDE LiteIDE是一款开源、跨平台的轻量级Go语言集成开发环境(IDE)。 支持的操作系统 Windows x86 (32-bit or 64-bit) Linux x86 (32-bit or 64-bit) 下载地址 :http://sourceforge.net/projects/liteide/files/ 源码地址 :https://github.com/visualfc/liteide 简单编辑器推荐使用Sublime Text
Go 语言学习资料 官网:https://golang.org/ 中文学习网站: https://www.w3cschool.cn/go/ https://studygolang.com/ http://www.runoob.com/go/go-tutorial.html 网站有很多实例代码可以参考 https://www.yiibai.com/go/
1.Go 语言环境安装
Go 语言支持以下系统:
Linux FreeBSD Mac OS X(也称为 Darwin) Window
1.1 UNIX/Linux/Mac OS X, 和 FreeBSD 安装
以下介绍了在UNIX/Linux/Mac OS X, 和 FreeBSD系统下使用源码安装方法: 1、下载源码包:go1.4.linux-amd64.tar.gz。 2、将下载的源码包解压至 /usr/local目录。 tar -C /usr/local -xzf go1.4.linux-amd64.tar.gz 3、将 /usr/local/go/bin 目录添加至PATH环境变量: export PATH=$PATH:/usr/local/go/bin 注意:MAC 系统下你可以使用 .pkg 结尾的安装包直接双击来完成安装,安装目录在 /usr/local/go/ 下。
1.2 Windows 系统下安装
Windows 下可以使用 .msi 后缀(在下载列表中可以找到该文件,如go1.4.2.windows-amd64.msi)的安装包来安装。 默认情况下.msi文件会安装在 c:\Go 目录下。你可以将 c:\Go\bin 目录添加到 PATH 环境变量中。添加后你需要重启命令窗口才能生效。 安装测试 创建工作目录 C:\>Go_WorkSpace。 文件名: test.go,代码如下:
package main import "fmt" func main() { fmt.Println("Hello, World!") }
使用 go 命令执行以上代码输出结果如下: C:\Go_WorkSpace>go run test.go Hello, World!
2.Go 语言结构
Go Hello World 实例 Go 语言的基础组成有以下几个部分:
包声明 引入包 函数 变量 语句 & 表达式 注释
接下来让我们来看下简单的代码,该代码输出了"Hello World!":
package main import "fmt" func main() { /* 这是我的第一个简单的程序 */ fmt.Println("Hello, World!") }
执行 Go 程序 让我们来看下如何编写 Go 代码并执行它。步骤如下:
(1)打开编辑器如Sublime2,将以上代码添加到编辑器中。 (2)将以上代码保存为 hello.go (3)打开命令行,并进入程序文件保存的目录中。 (4)输入命令 go run hello.go 并按回车执行代码。 (5)如果操作正确你将在屏幕上看到 "Hello World!" 字样的输出。
3.Go 语言数据类型
在 Go 编程语言中,数据类型用于声明函数和变量。
数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。
Go 语言按类别有以下几种数据类型:
类型和描述 (1)布尔型:布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。 (2)数字类型:整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码。 (3)字符串类型:字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本。 (4)派生类型,包括: (a) 指针类型(Pointer) (b) 数组类型 (c) 结构化类型(struct) (d) Channel 类型 (e) 函数类型 (f) 切片类型 (g) 接口类型(interface) (h) Map 类型
数字类型 Go 也有基于架构的类型,例如:int、uint 和 uintptr。 类型和描述 uint8:无符号 8 位整型 (0 到 255) uint16:无符号 16 位整型 (0 到 65535) uint32:无符号 32 位整型 (0 到 4294967295) uint64:无符号 64 位整型 (0 到 18446744073709551615) int8:有符号 8 位整型 (-128 到 127) int16:有符号 16 位整型 (-32768 到 32767) int32:有符号 32 位整型 (-2147483648 到 2147483647) int64:有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)
浮点型: 类型和描述 float32:IEEE-754 32位浮点型数 float64:IEEE-754 64位浮点型数 complex64:32 位实数和虚数 complex128:64 位实数和虚数
其他数字类型 以下列出了其他更多的数字类型: 类型和描述 byte:类似 uint8 rune:类似 int32 uint:32 或 64 位 int:与 uint 一样大小 uintptr:无符号整型,用于存放一个指针
4.Go 语言变量和常量
4.1变量
Go 语言变量名由字母、数字、下划线组成,其中首个字母不能为数字。 声明变量的一般形式是使用 var 关键字: var identifier type
变量声明 第一种,指定变量类型,声明后若不赋值,使用默认值。 var v_name v_type v_name = value
第二种,根据值自行判定变量类型。 var v_name = value
第三种,省略var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误。 v_name := value // 例如 var a int = 10 var b = 10 c := 10
多变量声明 //类型相同多个变量, 非全局变量 var vname1, vname2, vname3 type vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3 //和python很像,不需要显示声明类型,自动推断
vname1, vname2, vname3 := v1, v2, v3 //出现在:=左侧的变量不应该是已经被声明过的,否则会导致编译错误
// 这种因式分解关键字的写法一般用于声明全局变量 var ( vname1 v_type1 vname2 v_type2 )
4.2常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量。 常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。 常量的定义格式: const identifier [type] = value
你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。 显式类型定义: const b string = "abc" 隐式类型定义: const b = "abc" 多个相同类型的声明可以简写为: const c_name1, c_name2 = value1, value2
以下实例演示了常量的应用:
package main import "fmt" func main() { const LENGTH int = 10 const WIDTH int = 5 var area int const a, b, c = 1, false, "str" //多重赋值
area = LENGTH * WIDTH fmt.Printf("面积为 : %d", area) println() println(a, b, c) }
以上实例运行结果为: 面积为 : 50 1 false str
常量还可以用作枚举: const ( Unknown = 0 Female = 1 Male = 2 ) 数字 0、1 和 2 分别代表未知性别、女性和男性。 常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过:
package main import "unsafe" const ( a = "abc" b = len(a) c = unsafe.Sizeof(a) ) func main(){ println(a, b, c) }
以上实例运行结果为:abc 3 16
4.3iota iota,特殊常量,可以认为是一个可以被编译器修改的常量。
在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。
iota 可以被用作枚举值: const ( a = iota b = iota c = iota )
第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式: const ( a = iota b c )
iota 用法 package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" //独立值,iota += 1 e //"ha" iota += 1 f = 100 //iota +=1 g //100 iota +=1 h = iota //7,恢复计数 i //8 ) fmt.Println(a,b,c,d,e,f,g,h,i) }
以上实例运行结果为:
0 1 2 ha ha 100 100 7 8
再看个有趣的的 iota 实例:
package main import "fmt" const ( i=1<<iota j=3<<iota k l )
func main() { fmt.Println("i=",i) fmt.Println("j=",j) fmt.Println("k=",k) fmt.Println("l=",l) } 以上实例运行结果为: i= 1 j= 6 k= 12 l= 24
iota 表示从 0 开始自动加 1,所以 i=1<<0, j=3<<1(<< 表示左移的意思),即:i=1, j=6,这没问题,关键在 k 和 l,从输出结果看 k=3<<2,l=3<<3。 简单表述: i=1:左移 0 位,不变仍为 1; j=3:左移 1 位,变为二进制 110, 即 6; k=3:左移 2 位,变为二进制 1100, 即 12; l=3:左移 3 位,变为二进制 11000,即 24。
5.Go 语言运算符 运算符用于在程序运行时执行数学或逻辑运算。
Go 语言内置的运算符有: (1)算术运算符 (2)关系运算符 (3)逻辑运算符 (4)位运算符 (5)赋值运算符 (6)其他运算符
5.1算术运算符 下表列出了所有Go语言的算术运算符。假定 A 值为 10,B 值为 20。
运算符 描述 实例 + 相加 A + B 输出结果 30 - 相减 A - B 输出结果 -10 * 相乘 A * B 输出结果 200 / 相除 B / A 输出结果 2 % 求余 B % A 输出结果 0 ++ 自增 A++ 输出结果 11 -- 自减 A-- 输出结果 9
5.2关系运算符 下表列出了所有Go语言的关系运算符。假定 A 值为 10,B 值为 20。
运算符 描述 实例 == 检查两个值是否相等,如果相等返回 True 否则返回 False。 (A == B) 为 False != 检查两个值是否不相等,如果不相等返回 True 否则返回 False。 (A != B) 为 True > 检查左边值是否大于右边值,如果是返回 True 否则返回 False。 (A > B) 为 False < 检查左边值是否小于右边值,如果是返回 True 否则返回 False。 (A < B) 为 True >= 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。 (A >= B) 为 False <= 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。 (A <= B) 为 True
5.3逻辑运算符 下表列出了所有Go语言的逻辑运算符。假定 A 值为 True,B 值为 False。
运算符 描述 实例 && 逻辑 AND 运算符。 如果两边的操作数都是 True,则条件 True,否则为 False。 (A && B) 为 False || 逻辑 OR 运算符。 如果两边的操作数有一个 True,则条件 True,否则为 False。 (A || B) 为 True ! 逻辑 NOT 运算符。 如果条件为 True,则逻辑 NOT 条件 False,否则为 True。 !(A && B) 为 True
5.4位运算符 位运算符对整数在内存中的二进制位进行操作。
下表列出了位运算符 &, |, 和 ^ 的计算:
p q p & q p | q p ^ q 0 0 0 0 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 1
Go 语言支持的位运算符如下表所示。假定 A 为60,B 为13:
运算符 描述 实例 & 按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。 (A & B) 结果为 12, 二进制为 0000 1100 | 按位或运算符"|"是双目运算符。 其功能是参与运算的两数各对应的二进位相或 (A | B) 结果为 61, 二进制为 0011 1101 ^ 按位异或运算符"^"是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (A ^ B) 结果为 49, 二进制为 0011 0001 << 左移运算符"<<"是双目运算符。左移n位就是乘以2的n次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。 A << 2 结果为 240 ,二进制为 1111 0000 >> 右移运算符">>"是双目运算符。右移n位就是除以2的n次方。 其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。 A >> 2 结果为 15 ,二进制为 0000 1111
5.5赋值运算符 下表列出了所有Go语言的赋值运算符。
运算符 描述 实例 = 简单的赋值运算符,将一个表达式的值赋给一个左值 C = A + B 将 A + B 表达式结果赋值给 C += 相加后再赋值 C += A 等于 C = C + A -= 相减后再赋值 C -= A 等于 C = C - A *= 相乘后再赋值 C *= A 等于 C = C * A /= 相除后再赋值 C /= A 等于 C = C / A %= 求余后再赋值 C %= A 等于 C = C % A <<= 左移后赋值 C <<= 2 等于 C = C << 2 >>= 右移后赋值 C >>= 2 等于 C = C >> 2 &= 按位与后赋值 C &= 2 等于 C = C & 2 ^= 按位异或后赋值 C ^= 2 等于 C = C ^ 2 |= 按位或后赋值 C |= 2 等于 C = C | 2
5.6其他运算符 下表列出了Go语言的其他运算符。
运算符 描述 实例 & 返回变量存储地址 &a; 将给出变量的实际地址。 * 指针变量。 *a; 是一个指针变量
5.7运算符优先级 有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:
优先级 运算符 7 ^ ! 6 * / % << >> & &^ 5 + - | ^ 4 == != < <= >= > 3 <- 2 && 1 ||
6.Go 语言条件语句
条件语句和描述 if语句:由一个布尔表达式后紧跟一个或多个语句组成。 if...else语句:if 语句后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。 if嵌套语句:你可以在 if 或 else if 语句中嵌入一个或多个 if 或 else if 语句。 switch语句:switch 语句用于基于不同条件执行不同动作。 select语句:select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
7.Go 语言循环语句
Go 语言提供了以下几种类型循环处理语句: 循环类型和描述 for 循环:重复执行语句块 循环嵌套:在 for 循环中嵌套一个或多个 for 循环
循环控制语句 循环控制语句可以控制循环体内语句的执行过程。 GO 语言支持以下几种循环控制语句: 控制语句 描述 break 语句 经常用于中断当前 for 循环或跳出 switch 语句 continue 语句 跳过当前循环的剩余语句,然后继续进行下一轮循环。 goto 语句 将控制转移到被标记的语句。
无限循环 如果循环中条件语句永远不为 false 则会进行无限循环,我们可以通过 for 循环语句中只设置一个条件表达式来执行无限循环: package main import "fmt" func main() { for true { fmt.Printf("这是无限循环。\n"); } }
8.Go 语言函数
函数定义,Go 语言函数定义格式如下:
func function_name( [parameter list] ) [return_types] { 函数体 }
函数定义解析: func:函数由 func 开始声明 function_name:函数名称,函数名和参数列表一起构成了函数签名。 parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。 return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。 函数体:函数定义的代码集合。
函数参数传递类型和描述 值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。 引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。 默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。
函数用法和描述 函数作为值:函数定义后可作为值来使用 闭包:闭包是匿名函数,可在动态编程中使用 方法:方法就是一个包含了接受者的函数
9.Go 语言变量作用域
作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。
Go 语言中变量可以在三个地方声明:
函数内定义的变量称为局部变量 函数外定义的变量称为全局变量 函数定义中的变量称为形式参数
局部变量 在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。
全局变量 在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。
形式参数 形式参数会作为函数的局部变量来使用。
初始化局部和全局变量 不同类型的局部和全局变量默认值为: 数据类型 初始化默认值 int 0 float32 0 pointer nil
10.Go 语言数组
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为 0,第二个索引为 1,以此类推。
声明数组 一维数组 var variable_name [SIZE] variable_type
二维数组 二维数组是最简单的多维数组,二维数组本质上是由一维数组组成的。二维数组定义方式如下: var arrayName [ x ][ y ] variable_type
Go 语言支持多维数组,以下为常用的多维数组声明方式: var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
variable_type 为 Go 语言的数据类型,variable_name为数组名
初始化数组,以下演示了数组初始化: var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} 初始化数组中 {} 中的元素个数不能大于 [] 中的数字。 如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小: var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
访问数组元素 数组元素可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值。例如: float32 salary = balance[9]
11.Go 语言指针
我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。 Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。
什么是指针 一个指针变量指向了一个值的内存地址。 类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下: var var_name *var-type
var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。以下是有效的指针声明:
var ip *int /* 指向整型*/ var fp *float32 /* 指向浮点型 */
如何使用指针,指针使用流程: (1)定义指针变量。 (2)为指针变量赋值。 (3)访问指针变量中指向地址的值。 (4)在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。
Go 空指针 当一个指针被定义后没有分配到任何变量时,它的值为 nil。 nil指针也称为空指针。 nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。 一个指针变量通常缩写为 ptr。
Go指针更多内容 Go 指针数组 Go 指向指针的指针 Go 向函数传递指针参数
12.Go 语言结构体
Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
定义结构体 结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体有中有一个或多个成员。type 语句设定了结构体的名称。结构体的格式如下: type struct_variable_type struct { member definition; member definition; ... member definition; }
一旦定义了结构体类型,它就能用于变量的声明,语法格式如下: variable_name := structure_variable_type {value1, value2...valuen}
访问结构体成员 如果要访问结构体成员,需要使用点号 (.) 操作符,格式为:"结构体.成员名"。
结构体指针 你可以定义指向结构体的指针类似于其他指针变量,格式如下: var struct_pointer *Books
以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前: struct_pointer = &Book1;
使用结构体指针访问结构体成员,使用 "." 操作符: struct_pointer.title;
13.Go 语言切片
Go 语言切片是对数组的抽象。 Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
定义切片 你可以声明一个未指定大小的数组来定义切片: var identifier []type
切片不需要说明长度。 或使用make()函数来创建切片: var slice1 []type = make([]type, len) 也可以简写为 slice1 := make([]type, len) 也可以指定容量,其中capacity为可选参数。 make([]T, length, capacity) 这里 len 是数组的长度并且也是切片的初始长度。
切片初始化 s :=[] int {1,2,3 } 直接初始化切片,[]表示是切片类型,{1,2,3}初始化值依次是1,2,3.其cap=len=3
s := arr[:] 初始化切片s,是数组arr的引用
s := arr[startIndex:endIndex] 将arr中从下标startIndex到endIndex-1 下的元素创建为一个新的切片
s := arr[startIndex:] 缺省endIndex时将表示一直到arr的最后一个元素
s := arr[:endIndex] 缺省startIndex时将表示从arr的第一个元素开始
s1 := s[startIndex:endIndex] 通过切片s初始化切片s1
s :=make([]int,len,cap) 通过内置函数make()初始化切片s,[]int 标识为其元素类型为int的切片
len() 和 cap() 函数 切片是可索引的,并且可以由 len() 方法获取长度。 切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。
空(nil)切片 一个切片在未初始化之前默认为 nil,长度为 0
切片截取 可以通过设置下限及上限来设置截取切片 [lower-bound:upper-bound]
append() 和 copy() 函数 如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。 copy 方法拷贝切片,append 方法向切片追加新元素。
14.Go 语言范围(Range)
Go 语言中 range 关键字用于for循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引值,在集合中返回 key-value 对的 key 值。
package main import "fmt" func main() { //这是我们使用range去求一个slice的和。使用数组跟这个很类似 nums := []int{2, 3, 4} sum := 0 for _, num := range nums { sum += num } fmt.Println("sum:", sum) //在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。 for i, num := range nums { if num == 3 { fmt.Println("index:", i) } } //range也可以用在map的键值对上。 kvs := map[string]string{"a": "apple", "b": "banana"} for k, v := range kvs { fmt.Printf("%s -> %s\n", k, v) } //range也可以用来枚举Unicode字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。 for i, c := range "go" { fmt.Println(i, c) } }
以上实例运行输出结果为: sum: 9 index: 1 a -> apple b -> banana 0 103 1 111
15.Go 语言Map(集合)
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。 Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
定义 Map 可以使用内建函数 make 也可以使用 map 关键字来定义 Map:
/* 声明变量,默认 map 是 nil */ var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */ map_variable := make(map[key_data_type]value_data_type)
如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对
delete() 函数 delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。
实例如下: package main import "fmt" func main() { /* 创建map */ countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}
fmt.Println("原始地图")
/* 打印地图 */ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap [ country ]) }
/*删除元素*/ delete(countryCapitalMap, "France") fmt.Println("法国条目被删除")
fmt.Println("删除元素后地图")
/*打印地图*/ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap [ country ]) } }
以上实例运行结果为: 原始地图 India 首都是 New delhi France 首都是 Paris Italy 首都是 Rome Japan 首都是 Tokyo 法国条目被删除 删除元素后地图 Italy 首都是 Rome Japan 首都是 Tokyo India 首都是 New delhi
16.Go 语言类型转换
类型转换用于将一种数据类型的变量转换为另外一种类型的变量。Go 语言类型转换基本格式如下: type_name(expression) type_name 为类型,expression 为表达式。
实例 以下实例中将整型转化为浮点型,并计算结果,将结果赋值给浮点型变量: package main import "fmt" func main() { var sum int = 17 var count int = 5 var mean float32
mean = float32(sum)/float32(count) fmt.Printf("mean 的值为: %f\n",mean) } 以上实例执行输出结果为: mean 的值为: 3.400000
17.Go 语言接口
Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
实例 /* 定义接口 */ type interface_name interface { method_name1 [return_type] method_name2 [return_type] method_name3 [return_type] ... method_namen [return_type] }
/* 定义结构体 */ type struct_name struct { /* variables */ }
/* 实现接口方法 */ func (struct_name_variable struct_name) method_name1() [return_type] { /* 方法实现 */ } ... func (struct_name_variable struct_name) method_namen() [return_type] { /* 方法实现*/ }
实例
package main import ( "fmt" ) type Phone interface { call() } type NokiaPhone struct { } func (nokiaPhone NokiaPhone) call() { fmt.Println("I am Nokia, I can call you!") } type IPhone struct { } func (iPhone IPhone) call() { fmt.Println("I am iPhone, I can call you!") } func main() { var phone Phone
phone = new(NokiaPhone) phone.call()
phone = new(IPhone) phone.call()
} 在上面的例子中,我们定义了一个接口Phone,接口里面有一个方法call()。然后我们在main函数里面定义了一个Phone类型变量,并分别为之赋值为NokiaPhone和IPhone。然后调用call()方法,输出结果如下: I am Nokia, I can call you! I am iPhone, I can call you!
18.Go 错误处理
Go 语言通过内置的错误接口提供了非常简单的错误处理机制。
error类型是一个接口类型,这是它的定义: type error interface { Error() string }
我们可以在编码中通过实现 error 接口类型来生成错误信息。
函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:
func Sqrt(f float64) (float64, error) { if f < 0 { return 0, errors.New("math: square root of negative number") } // 实现 }
在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了non-nil的error对象,将此对象与nil比较,结果为true,所以fmt.Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,请看下面调用的示例代码:
result, err:= Sqrt(-1)
if err != nil { fmt.Println(err) }
实例
package main import ( "fmt" ) // 定义一个 DivideError 结构 type DivideError struct { dividee int divider int } // 实现 `error` 接口 func (de *DivideError) Error() string { strFormat := ` Cannot proceed, the divider is zero. dividee: %d divider: 0 ` return fmt.Sprintf(strFormat, de.dividee) } // 定义 `int` 类型除法运算的函数 func Divide(varDividee int, varDivider int) (result int, errorMsg string) { if varDivider == 0 { dData := DivideError{ dividee: varDividee, divider: varDivider, } errorMsg = dData.Error() return } else { return varDividee / varDivider, "" } } func main() { // 正常情况 if result, errorMsg := Divide(100, 10); errorMsg == "" { fmt.Println("100/10 = ", result) } // 当被除数为零的时候会返回错误信息 if _, errorMsg := Divide(100, 0); errorMsg != "" { fmt.Println("errorMsg is: ", errorMsg) } }
执行以上程序,输出结果为: 100/10 = 10 errorMsg is: Cannot proceed, the divider is zero. dividee: 100 divider: 0
|
请发表评论