这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
Golang特点
1.高性能、高并发 2.语法简单、学习曲线平缓 3.丰富的标准库 4.完善的工具链 5.静态链接 6.快速编译 7.跨平台 8.垃圾回收
开发环境配置
下载windows安装器:
修改一些环境变量
go env -w GOPATH=工作区路径(我的是D:\Golang\code)
这里可能会遇到warning: go env -w GOPATH=... does not override conflicting OS environment variable
原因是这个变量已配置,无法进行覆盖,所以需要手动去修改
windows => 设置 => 主页 => 关于 => 高级系统设置 => 环境变量 => GOPATH
配置代理
$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct
安装vscode插件
然后就可以编码使用了
使用go run filename.go运行程序或使用go build filename.go将程序编译成二进制文件
基本语法
- 变量声明
一般使用var进行变量的声明
var varName [varType] = value
or
varName := value
such as:
var a, b, c int = 1, 2, 3
d := 4
常量声明 => 将var改为const
const a int = 1
- 基本类型
字符串、布尔、浮点数、整数
- 分支结构
if和 python一样不需要括号,但必须跟大括号
if 1 == 1 {
fmt.Println("pass")
}
switch分子结构
var caseExample int = 3
switch caseExample {
case 1:
fmt.Println("case 1")
case 2:
fmt.Println("case 2")
case 3:
fmt.Println("case 3")
default:
fmt.Println("case default")
}
switch {
case caseExample > 5:
fmt.Println("caseExample > 5")
case caseExample == 5:
fmt.Println("caseExample == 5")
default:
fmt.Println("default => caseExample < 5")
}
- 循环结构
没有while或do-while循环,只有for循环
for {
fmt.Println("loop")
break
}
for i := 1; i < 10; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i)
}
- 切片
使用make创建切片,使用append进行扩容追加,但append操作后需要赋值给源变量,本质是将扩容后的变量覆盖源变量
slice := make([]int, 3)
for i := 0; i < 3; i++ {
slice[i] = i
}
fmt.Println(slice)
fmt.Println(append(slice, 33))
fmt.Println(slice)
输出:
[0 1 2]
[0 1 2 33]
[0 1 2]
- map
使用make创建并指定key和value的元素类型,map内元素无序
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
m["three"] = 3
fmt.Println(m["two"])
//判断key是否存在
v, ok := m["four"]
if ok {
fmt.Println("exist four value =", v)
} else {
fmt.Println("not exist four")
}
//使用delete进行删除某个key-value
delete(m, "two")
//使用range进行遍历
for k, v := range m {
fmt.Println("key =", k, ", value =", v)
}
- 指针和结构体
go支持如c类似的指针和结构体
type user struct {
name string
age int
}
func main() {
fmt.Println("hello go")
a := 1
add(&a)
fmt.Println(a)
//初始化结构体
u := user{"zhangsan", 13}
fmt.Println(u)
changeStruct(&u)
fmt.Println(u)
}
func add(a *int) {
*a = *a + 1
}
func changeStruct(u *user) {
add(&u.age)
}
- Printf格式化
可用使用%v对任意类型变量进行打印
使用%+v获得详细结果
使用%#v获得更加详细的结果
type user struct {
name string
age int
}
func main() {
u := user{"lisi", 14}
fmt.Printf("%v\n", u)
fmt.Printf("%+v\n", u)
fmt.Printf("%#v\n", u)
}
输出:
{lisi 14}
{name:lisi age:14}
main.user{name:"lisi", age:14}
- json序列化
使用json.marshal进行序列化,使用json.unmarshal进行反序列化,但是结构体字段要大写,不然会序列化不出来
type user struct {
Name string
Age int
}
func main() {
fmt.Println("hello go")
u := user{"lisi", 14}
b, err := json.Marshal(u)
if err != nil {
}
fmt.Println(b)
fmt.Println(string(b))
json.Unmarshal(b, &u)
fmt.Println(u)
}
输出:
[123 34 78 97 109 101 34 58 34 108 105 115 105 34 125]
{"Name":"lisi"}
{lisi 14}
Go变量声明踩坑
众所周知,go声明变量可用使用 varName := value
今天遇到一个坑,相同逻辑的代码(比较简单,没涉及什么高级操作),使用java和python都没问题,但是到了go出现了个数组下标越界问题。后面检查发现了问题所在:变量的重复声明
在同一代码块中,变量不能重复声明如:
a := 1
a := 2
出现no new variables on left side of :=错误警告,但是!!!
当重复声明的变量一个在外面,一个在for循环里面却没有任何问题
var a int = 1
for i := 0; i < 2; i++ {
fmt.Println("f: ", a)
var a int = 2
fmt.Println("s: ", (a))
}
/*
运行结果:
f: 1
s: 2
f: 1
s: 2
*/
完全正确运行!!!!
我产生错误的原因是偷懒造成的
首先外部有个变量a
在循环内使用自定义函数get获得两个值同时赋给a和b,这里b还没定义,我想同时为a、b赋值但不行单独拿一行定义b,所以===> a, b := get(params),这样就内内部又定义了一个a,后面的对a的操作没有影响外部的a,因此外部a的值一直没变,但循环判断又是用到了外部a,导致错误出现;
下面是个模拟事故出现的程序逻辑:
func main() {
a := 0
arr := []int{1, 2, 3}
c := 0
for a < 2 {
a, b := get(c)
fmt.Println(arr[c], b)
c = a
a++
}
}
func get(p int) (int, int) {
return p + 1, p + 2
}