20190830
代码格式:
packge main//go代码所属于的包 要想生成Go可执行程序,建立main的包,包含一个main函数
import “fmt” //函数Println所在的包,使用import将需要的包包含进来,不得包含未使用的包
func main(){ //程序的入口,不带参数也不带返回值
fmt.Println(“hello world”)
}
常规函数定义:
func 函数名(参数列表)(返回值列表) {
// 函数体
}
- 变量
1.1变量的定义
引入关键字var,将类型信息放在变量名之后。
var v1 int
var v2 string
var v3 [10]int // 数组
var v4 []int // 数组切片
var v5 struct {
f int
}
var v6 *int // 指针
var v7 map[string]int // map, key为string类型, value为int类型
var v8 func(a int) int
多个变量的一次定义:
var (
v1 int
v2 string
)
1.2 变量的初始化
进行变量声明时的初始化,var可以保留,但已经不是必要的元素;
var v 1 int = 10 // 正确的使用方式1
var v2 = 10 // 正确的使用方式2,编译器可以自动推导出v2的类型
v3 := 10 // 正确的使用方式3,编译器可以自动推导出v3的类型
操作符:= à用于明确表达的同时进行变量的声明和初始化的工作,只用于新变量的声明,已经声明过的变量在进行上述操作将会报错。
1.3 变量赋值 初始化和变量赋值是两个不同的概念。
多重复值: i, j = j, i。交换i和j的值。
1.4 匿名变量
假 设 GetName() 函 数 的 定 义 如 下 , 它 返 回 3 个 值 , 分 别 为firstName 、 lastName 和
nickName:
func GetName() (firstName, lastName, nickName string) {
return "May", "Chan", "Chibi Maruko"
}
若只想获得nickName,则函数调用语句可以用如下方式编写:
_, _, nickName := GetName()
2、常量:常量是指编译期间就已知且不可改变的值。常量可以是数值类型(包括整型、浮点型和复数类型)、布尔类型、字符串类型等。
2.1 字面常量
-12
3.14159265358979323846 // 浮点类型的常量
3.2+12i // 复数类型的常量
true // 布尔类型的常量
"foo" // 字符串常量
字面常量更接近我们自然语言中的常量概念,它是无类型的。只要这个常量在相应类型的值域范围内,就可以作为该类型的常量,比如上面的常量-12,它可以赋值给int、 uint、 int32、int64、 float32、 float64、 complex64、 complex128等类型的变量。
2.2 常量定义
使用const关键字,给字面常量一个友好的名字。
const Pi float64 = 3.14159265358979323846
const zero = 0.0 // 无类型浮点常量
const (
size int64 = 1024
eof = -1 // 无类型整型常量
)
const u, v float32 = 0, 3 // u = 0.0, v = 3.0,常量的多重赋值
const a, b, c = 3, 4, "foo"
// a = 3, b = 4, c = "foo", 无类型整型和字符串常量
2.3 预定义常量:true、 false和iota。
iota比较特殊,可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1。
const ( // iota被重设为0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const (
a = 1 << iota // a == 1 (iota在每个const开头被重设为0)
b = 1 << iota // b == 2
c = 1 << iota // c == 4
)
const (
u = iota * 42 // u == 0
v float64 = iota * 42 // v == 42.0
w = iota * 42 // w == 84
)
const x = iota // x == 0 (因为iota又被重设为0了)
const y = iota // y == 0 (同上)
2.4 枚举:一系列相关的常量。
const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
numberOfDays // 这个常量没有导出
)
大写字母开头的常量在外包外是可见的,小写字母开头的常量为包内私有。
3、类型
内置基础类型:
布尔类型: bool。
整型: int8、 byte、 int16、 int、 uint、 uintptr等。
浮点类型: float32、 float64。
复数类型: complex64、 complex128。
字符串: string。
字符类型: rune。
错误类型: error。
复合类型:
指针(pointer)
数组(array)
切片(slice)
字典(map)
通道(chan)
结构体(struct)
接口(interface)
布尔类型:
var v1 bool
v1 = true
v2 := (1 == 2) // v2也会被推导为bool类型
布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换。
整型:
类型 长度(字节) 值范围
int8 1 -128 ~ 127
uint8(即byte) 1 0 ~ 255
int16 2 -32 768 ~ 32 767
uint16 2 0 ~ 65 535
int32 4 -2 147 483 648 ~ 2 147 483 647
uint32 4 0 ~ 4 294 967 295
int64 8 -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807
uint64 8 0 ~ 18 446 744 073 709 551 615
int 平台相关 平台相关
uint 平台相关 平台相关
uintptr 同指针 在32位平台下为4字节, 64位平台下为8字节
不同的整型之间不可以进行比较,可以通常强制类型转换来实现比较,而且各种不同类型值之间的整型都可以直接好字面常量(literal)进行比较。
浮点型
float32等价于C语言的float类型,float64等价于C语言的double类型。
判断两个浮点数是否相等:
import "math"
// p为用户自定义的比较精度,比如0.00001
func IsEqual(f1, f2, p float64) bool {
return math.Fdim(f1, f2) < p
复数类型
获取实部和虚部:对于一个复数z = complex(x, y),就可以通过Go语言内置函数real(z)获得该复数的实部,也就是x,通过imag(z)获得该复数的虚部,也就是y。
字符串
var str string // 声明一个字符串变量
str = "Hello world" // 字符串赋值
ch := str[0] // 取字符串的第一个字符
fmt.Printf("The length of \"%s\" is %d \n", str, len(str))
fmt.Printf("The first character of \"%s\" is %c.\n", str, ch)
字符串的内容不能在初始化之后进行改动。
字符串的操作:
(1)基本操作
x + y 字符串连接 "Hello" + "123" // 结果为Hello123
len(s) 字符串长度 len("Hello") // 结果为5
s[i] 取字符 "Hello" [1] // 结果为’e’
(2)字符串的遍历
a:以字节数组的方式进行遍历:
str := "Hello,世界"
n := len(str)
for i := 0; i < n; i++ {
ch := str[i] // 依据下标取字符串中的字符,类型为byte
fmt.Println(i, ch)
}
b:以Unicode方式进行遍历:
str := "Hello,世界"
for i, ch := range str {
fmt.Println(i, ch)//ch的类型为rune
}
字符类型
两种字符类型:byte和rune
数组:同一类型的数据的集合。
[32]byte // 长度为32的数组,每个元素为一个字节
[2*N] struct { x, y int32 } // 复杂类型数组
[1000]*float64 // 指针数组
[3][5]int // 二维数组
[2][2][2]float64 // 等同于[2]([2]([2]float64))
(1)元素的访问
for i := 0; i < len(array); i++ {
fmt.Println("Element", i, "of array is", array[i])
}
Go提供了关键字range,用于便捷的访问容器中的元素,第一个返回值是数组的下标,第二个返回值是元素的值。
for i, v := range array {
fmt.Println("Array element[", i, "]=", v)
}
(2)值类型
Go语言中数组是一个值类型,所有的值类型变量在赋值合作为参数进行传递时都将产生复制动作。如果是将数组作为参数类型传递给函数,函数内部是无法对数组的内容进行改变的,因为传递的参数只是数组的一次复制。
数组切片:slice
数组切片就像一个指向数组的指针,实际上它拥有自己的数据结构,而不仅仅是个指针。数组切片的数据结构可以抽象为以下3个变量:
一个指向原生数组的指针;数组切片中的元素的个数;数组切片已分配的存储空间。
(1)创建数组切片
基于数组的方法:数组切片可以基于一个已存在的数组创建。数组切片可以只使用数组的一部分元素或者整个数组来创建,甚至可以创建一个比所基于的数组还要大的数组切片。
直接创建:使用make()来直接创建切片。
创建一个初始元素个数为5的数组切片,元素初始值为0:
mySlice1 := make([]int, 5)
创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间:
mySlice2 := make([]int, 5, 10)
直接创建并初始化包含5个元素的数组切片:
mySlice3 := []int{1, 2, 3, 4, 5}
(2)元素遍历:一个一个的遍历或者是使用range来进行遍历操作。
(3)动态增减元素:
cap()函数返回的是数组切片分配的空间大小,而len()函数返回的是数组切片中当前所存储的元素个数。append()函数向数组切片的最后继续添加元素,如mySlice = append(mySlice, 1, 2, 3)
(4)基于数组切片创建数组切片
oldSlice := []int{1, 2, 3, 4, 5}
newSlice := oldSlice[:3] // 基于oldSlice的前3个元素构建新数组切片
选择的oldSlice甚至可以是超过所包含的元素的个数,多出的就补0。
(5)内容复制
Copy()函数,用于将内容从一个数组切片复制到另一个数组切片。如果加入的两个数组切片不一样大,就会按其中较小的那个数组切片的元素个数进行复制。