1、Go语言环境安装
参考教程:https://www.runoob.com/go/go-environment.html
安装包下载地址:https://golang.google.cn/dl/
Windows版本的安装包为go1.13.7.windows-amd64.msi。
安装完成配置Path环境变量:添加路径E:\Go\bin。
在命令行测试环境搭建是否成功(编写Go语言的Hello World程序):
在目录H:\IDEAWorkspace\下创建hello.go文件如下:
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
进入目录H:\IDEAWorkspace
C:\Users\DELL>H:
H:\>cd H:\IDEAWorkspace
H:\IDEAWorkspace>go run hello.go
hello, world
或者
H:\IDEAWorkspace>go build
H:\IDEAWorkspace>IDEAWorkspace
hello, world
2、Go语言基础语法
(1)数据类型
布尔型:go语言用bool表示。
整型:go语言里面有int8,int16,int32,int64,分别对应Java中的byte,short,int,long,同时go语言里面还有专门表示无符号数的uint8,uint16,uint32和uint64。
浮点型:float32,float64。
字符串类型:string。
go语言中的uint8表示Java中的byte类型,go语言中的rune表示int32类型,也就是4个字节有符号的整数,对应Java中的int。即byte是uint8的别名,rune是int32的别名。
除此之外,go语言数据类型包括一些派生类型:指针类型(Pointer)、数组类型、结构体类型(struct)、channel类型、函数类型、切片类型、接口类型(interface)、map类型等。
(2)变量的声明与赋值
1)先声明再赋值
var name string
name = "csdn"
2)声明并且赋值
var name = "csdn" // 编译器会根据值自行判定变量类型
3)使用:=
声明并且赋值
name := "csdn" // 这里省略var关键字,效果和第二种是一样的
(3)if条件语句
if 布尔表达式 {
/* 在布尔表达式为true时执行 */
}
需要注意的是,Go中的if条件语句没有括号,例如:
if a == 10 {
/* 如果条件为true则执行以下语句 */
fmt.Println("a == 10")
}
此外,if还有另外一种形式,它包含一个statement可选语句部分,该组件在条件判断之前运行。它的语法是:
if statement; condition {
}
例如:
if a:=1; a<10 {
/* 如果条件为true,则执行以下语句 */
fmt.Println("a<10")
}
(4)循环语句
1)格式一:和其他语言的for语法类似
for init; condition; post {
}
init:一般为赋值表达式,给控制变量赋初值。
condition:关系表达式或逻辑表达式,循环控制条件。
post:一般为赋值表达式,给控制变量增量或减量。
例如:
for i := 1; i < 10; i++ {
fmt.Println("i=", i)
}
2)格式二:跟while循环类似
for condition {}
例如:
for 0 == 0 {}
for true {}
3)格式三:死循环,类似while(true) {}
for { }
例如:
for {
server.Listen(8080) // 服务器监听8080端口
}
(5)结构体
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合(相当于Java中的类class)。
go语言中的结构体定义如下:
type identifier struct {
field1 type1
field2 type2
}
用结构体可以表示一个具有某一特征的对象。field1,field2是对象的属性,type1,type2是属性的数据类型。例如:
type Person struct {
name string
age uint32
birth string
height float32
weight float32
}
第一种结构体赋值方式:
t := new(T) // 变量t是一个指向T的指针,此时结构体字段的值是它们所属类型的零值
person := new(Person)
第二种结构体赋值方式:
t := &T{}
&T{}这种语法叫做混合字面量语法(composite literal syntax),类似&struct1 {a, b, c},这种混合字面量语法是一种简写,底层仍然会调用new(),这里值的顺序必须按照字段顺序来写。
person := &Person {name: "juejin", age: 12}
如果要访问结构体成员,需要使用点号 . 操作符,格式为:“结构体.成员名”。
例如:
person := &Person {name: "juejin", age: 12}
fmt.Printf("name: %s, age: %d", person.name, person.age)
(6)数组
1)数组是有序的元素序列,go中数组语法如下:
var variable_name [SIZE] variable_type
例如:
// 定义一个10个长度string类型的数组array
var array[10] string
// 数组赋值
array[0] = "go"
array[1] = "java"
array[2] = "c++"
数组赋值:上面代码可以看出,直接通过访问数组下标即可对数组元素进行赋值。
2)数组初始化:声明时初始化,语法如下:
var variable_name = [SIZE]variable_type {value1, value2,...}
例如:
var array = [5]string {"go", "java", "c++"}
3)数组遍历
普通for循环遍历,例如:
for i := 0; i < 5; i++ {
fmt.Printf("array[%d] = %s \n", i, array[i])
}
for range遍历,这是go里面一种特有的遍历方式,例如:
// 这段代码可以实现跟上面代码相同的效果
for index, value := range array {
fmt.Printf("array[%d] = %s \n", index, value)
}
上面代码中,index即为数组元素下标,value即为数组元素的值,假如不需要使用到index或者value,可以用_进行代替。例如:
// 这段代码可以实现跟上面代码相同的效果
for _, value := range array {
fmt.Printf("value = %s \n", value)
}
(7)切片
切片:go语言提供了一种类似“动态数组”结构的数据类型,这种类型就是切片slice。
slice的本质是一个数据结构,实现了对数组操作的封装。
切片slice的声明语法如下:
var identifier []type
例如:
// 声明一个为int64类型的切片
var array []int64
slice和数组的声明语法是不同的,go语言中声明数组时是需要指定长度的,例如:
// 声明一个为int64类型长度为10的数组
var array[10] int64
初始化操作也不一样,对slice的初始化是使用make初始化。
// 初始化一个int64类型的切片
array = make( []int64, 10)
而对数组的初始化是:
array = [10]int64 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
切片slice的常用方法:append,实现对slice元素的添加,例如:
array := make([]int64, 10)
// 往切片中添加两个元素
array = append(array, 1)
array = append(array, 2)
截取:可以通过设置下限及上限来截取切片 [lower-bound : upper-bound],例如:
package main
import "fmt"
func main() {
/* 创建切片 */
numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
/* 打印原始切片 */
fmt.Println("numbers == ", numbers) // numbers == [0 1 2 3 4 5 6 7 8]
/* 打印子切片从索引1(包含)到索引4(不包含) */
fmt.Println("numbers[1: 4] == ", numbers[1: 4]) // numbers[1: 4] == [1 2 3]
/* 默认下限为0 */
fmt.Println("numbers[:3] == ", numbers[:3]) // numbers[:3] == [0 1 2]
/* 默认上限为len(s) */
fmt.Println("numbers[4: ] == ", numbers[4: ]) // numbers[4: ] == [4 5 6 7 8]
}
获取切片长度:通过len方法。
len(slice)
遍历:和数组一样,slice可以通过range关键字进行遍历。例如:
package main
import "fmt"
func main() {
// 使用range去求一个slice的和
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println("sum:", sum)
for i, num := range nums {
if num == 3 {
fmt.Println("index:", i)
}
}
}
(8)map
map是一种无序的键值对的集合。go语言中的语法如下:
/* 声明变量,map的默认值是nil map */
var map_variable map[key_data_type]value_data_type
例如:
var dataMap map[string]string
map初始化:map可以使用make进行初始化。
/* 使用make函数 */
map_variable := make(map[key_data_type]value_data_type)
例如:
dataMap := make(map[string]string)
如果不初始化map,那么就会创建一个nil map,nil map不能用来存放键值对。例如下面代码会执行失败:
package main
func main(){
var dataMap map[string]string
dataMap["csdn"] = "hello csdn"
}
输出:panic: assignment to entry in nil map
和数组不同,map可以根据新增的key-value对动态地伸缩,因此它不存在固定长度或者最大限制。但是可以选择标明map的初始容量capacity,语法如下:
make(map[keytype]valuetype, capacity)
例如:
dataMap := make(map[string]string, 20)
map遍历:和slice相似,map的遍历同样也可以使用for range进行遍历,例如:
kvs := map[string]string {"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
map基本操作
假设有一个map m:
设置/修改元素值:
m[key] = elem
获取元素:
elem = m[key]
删除元素:
delete(m, key)
检测某个键是否存在:
elem, ok = m[key]
如果key在m中,ok为true,否则,ok为false,并且elem是map的元素类型的零值。
同样的,当从map中读取某个不存在的键时,结果是map的元素类型的零值。
(9)函数
go语言函数定义格式如下:
func function_name([parameter_list])[return_types]{
函数体
}
与许多后端语言不同的是,go语言中的函数是支持多返回值的,比如我们将上述函数修改一下,实现取两个数最大值和最小值的功能。
// 此函数实现了取两个数最大值的功能
func max(a int32, b int32) int32 {
if a > b {
return a
} else {
return b
}
}
// 此函数实现了取两个数最大值和最小值的功能
func getMaxAndMin(a int32, b int32)(int32, int32) {
if a > b {
return a, b
} else {
return b, a
}
}
(10)方法
go语言还有一种特殊的函数,叫做方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。语法格式如下:
func (variable_name variable_data_type) function_name([parameter_list])[return_type] {
/* 函数体 */
}
例如:
// 我们用面向对象的思想实现一个封装的结构体
type Person struct {
name string // 姓名
age uint32 // 年龄
}
// 获取姓名
func (p *Person) GetName() string {
return p.name
}
// 设置姓名
func (p *Person) SetName(name string) {
p.name = name
}
3、Go语言实例
import "fmt"
type Person interface {
SetName(string)
GetName() string
}
type person struct {
name string
}
func (p *person) GetName() string {
return p.name
}
func (p *person) SetName(name string) {
p.name = name
}
func doSomething(p Person) {
fmt.Println(p.GetName())
}
func main() {
p := &person{
name : "Tom"
}
fmt.Println(p.GetName())
doSomething(p)
}