工程
- 官网下载安装goland
- 打开一个go项目之后,在terminal下执行安装依赖项
- 注意export是Linux/Mac OS中的命令,Windows中应使用如下例所示
$env:GO111MODULE = "on"
参考解决
3. 添加service.go配置文件
4. run goland代码,出现***.log即run成功。前三步没问题不能run时可重启(reload disk)。
理论
变量
变量可以通过变量名访问。Go语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。声明变量的一般形式是使用var关键字:
var identifier type
可以一次声明多个变量:
var identifier1, identifier2 type
变量声明
- 指定变量类型,如果没有初始化则变量默认为零值。
var v_name v_type
v_name = value
- 数值类型(包括complex64/128)为0
- 布尔类型为false
- 字符串为""(空字符串)
- 以下几种类型为nil:
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口
- 根据值自行判定变量类型
var v_name = value
- 如果变量已经使用var声明过了,再使用 := 声明变量,就产生编译错误,格式:
v_name := value
多变量声明
//类型相同多个变量,非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3 //不需要显示声明类型,自动推断
vname1, vname2, vname3 := v1, v2, v3 //出现在:=左侧的变量不应该是已经被声明
过的,否则会导致编译错误
// 这种因式分解关键字的写法一般用于声明全局变量
var (
vname1 v_type1
vname2 v_type2
)
数据
- array
- 数组是值类型,赋值和传参会复制整个数组,而不是指针。
- 数组畅度必须是常量,且是类型的组成部分。[2]int和[3]int是不同类型。
- 支持’‘==’‘、’‘!=’'操作符,因为内存总是被初始化过的。
- 指针数组[n]*T, 数组指针 *[n]T。
可用复合语句初始化。
a := [3]int{
1,2} //未初始化元素值为0。
b := [...]int{
1,2,3,4} //通过初始化值确定数组长度。
c := [5]int{
2: 100, 4:100} //通过索引号初始化元素。
d := [...]struct{
name string
age uint8
}{
{
"user1", 10}, //可省略元素类型。
{
"user2", 20}, //别忘了最后一行的逗号,
}
支持多维数组。
a := [2][3]int{
{
1,2,3}, {
4,5,6}}
b := [...][2]int{
{
1,1}, {
2,2}, {
3,3}} //第2纬度不能用"..."。
值拷贝行为会造成性能问题,通常会建议使用slice,或数组指针。
func test(x [2]int){
fmt.Printf("x: %p\n", &a)
test(a)
fmt.Println(a)
}
输出:
a: 0x2101f9150
x: 0x2101f9170
[0,0]
内置函数len和cap都返回数组长度(元素数量)。
a := [2]int{
}
println(len(a), cap(a)) //2, 2
Slice
slice并不是数组或数组指针。它通过内部指针和相关属性引用数组片段,以实现变长方案。
runtime.h
struct Slice
{
//must not move anything
byte* array; //actual data
uintgo len; //number of elements
uintgo cap; //allocated number of elements
}
- 引用类型。但自身是结构体,值拷贝传递。
- 属性len表示可用元素数量,读写操作不能超过该限制。
- 属性cap表示最大扩张容量,不能超出数组限制。
- 如果slice == nil, 那么len、cap结果都等于0。
data := [...]int{
0,1,2,3,4,5,6}
slice := data[1:4:5] // [low:high:max]
读写操作实际目标是底层数组,只需注意索引号的差别。
data := [...]int{
0,1,2,3,4,5}
s := data[2:4]
s[0] += 100
s[1] += 200
fmt.Println(s)
fmt.Println(data)
输出:
[102 103]
[0 1 102 203 4 5]
可直接创建slice对象,自动分配底层数组。
s1 := []int{
0, 1, 2, 3, 8: 100} //通过初始化表达式构造,可使用索引号。
fmt.Println(s1, len(s1), cap(s1))
s2 := make([]int, 6, 8) //使用make创建,指定len和cap值。
fmt.Println(s2, len(s2), cap(s2))
s3 := make([]int, 6) //省略cap,相当于cap = len。
fmt.Println(s3, len(s3), cap(s3))
输出:
[0 1 2 3 0 0 0 0 100] 9 9
[0 0 0 0 0 0] 6 8
[0 0 0 0 0 0] 6 6
使用make动态创建slice,避免了数组必须用常量做长度的麻烦。还可用指针直接访问底层数组,退化成普通数组操作。
s := []int{
0, 1, 2, 3}
p := &s[2] // *int,获取底层数组元素指针。
*p += 100
fmt.Println(s)
输出:
[0 1 102 3]
至于 [][]T,是指元素类型为[]T。
data := [][]int{
[]int{
1, 2, 3},
[]int{
100, 200},
[]int{
11, 22, 33, 44},
}
可直接修改struct array/slice 成员。
d := [5]struct