这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
设计思想
- 传递给函数的参数,如果想要改变该参数的值,一定传递的是指针。这个无论自己写代码还是看api,都应遵循这个原则。
🍱包
1 声明入口包
package main
2 导包
import (
"fmt"
)
3 主函数
func main(){
fmt.println("hello world!")
}
🥯编译
1 运行
go run path/main.go
2 编译
go build path/main.go
./main
🌭变量
go是一门强类型语言,每一个变量都有他自己的类型,似乎golang里没有字符这个概念。
1 变量类型
1 字符串
字符串可以直接用加号拼接,也可以直接用等于号比较两个字符串
2 整数
3 布尔型
4 浮点型
2 变量声明
var name="Jack" // 直接使用var依靠自动推断
var a,b int=1,2 // 使用var和类型显示的进行声明
c:=3.145 // 使用冒号进行声明
3 常量声明
const name string="foo"
🍶关键字
1 If
- 判断表达式没有括号
- 必须写大括号,不能写到一行
2 For
- golang里没有while关键字,只有for一个关键字
- 类比c中for循环的三段,每一段都可以省略,甚至三段可以全省掉
3 Switch
- 不同于c系语言中的switch,只要不break,就会一直执行下去,而golang中无需break,只会执行一条。
- 可以替代if else做一个判断分支
🧶数组
一般很少用数组,因为他的长度是固定的,用的更多的是切片
🎇切片
1 构造
相当于可变长度的数组,使用make来创建切片
s:=make([]string,3)
2 追加 append
可以用append来追加元素,但是追加后的元素必须赋值给原变量(事实上go完全是一门过程型语言,所以他有点函数式变成的意味,所以本地改的函数比较少)。
Ps:注意这个追加是在第四个位置追加,而不是在第二个位置追加,追加一个元素后,这个切片的长度是4。
s[0]="a"
s=append(s,"1")
fmt.println(s)
3 拷贝
先创建一个新的与原来切片等长的切片,然后进行拷贝
c:=make([]string,len(s))
copy(c,s)
4 切片
类似python的切片操作
m:=s[:3]
🎍map
Golang 中的 map 完全是无序的,不会按照字母顺序输出也不会按照插入顺序输出,而是一个偏随机的方式。
1 构造
map 的构造也是使用 make。
m:=make(map[string]int)
m["one"]=1
m["two"]=2
m2:=map[string]int{"one":1,"tow":2}
2 删除
delete(s,"one")
3 获取
one:=s["one"]
tow,ok:=s[two]
🎐range
用来遍历map、切片和数组
s := []string{"one", "two"}
var b = make([]string, 4)
b = append(b, "five")
var m = make(map[string]int)
m["one"] = 1
for index, num := range m {
fmt.Println("index", index, "num", num)
}
for index, num := range b {
fmt.Println("index", index, "num", num)
}
for index, num := range s {
fmt.Println("index", index, "num", num)
}
//结果
//index one num 1
//index 0 num
//index 1 num
//index 2 num
//index 3 num
//index 4 num five
//index 0 num one
//index 1 num two
函数
-
golang是一门变量类型后置的语言。对于函数一般会返回多个值,第一个值是真正的返回值,第二个值是错误信息.
-
感觉golang'的工具函数很多都是大写开头的,这也可能是赋予对外的接口。
指针
功能有限,主要的一个功能就是对传入的参数进行修改。
func add2(n *int){
*n+=2
}
结构体
结构体内部元素之间按行划分,不用分隔符
type user struct{
name string
password string
}
多种初始化方法:
a:=user{name:"wang",password:"1024"}
b:=user{"li","1407"}
c:=user{name:"wang"}
c.password="1024"
结构体方法,类似面向对象的内部函数,主要有两种,一种是带指针,一种是不带指针,带指针的就可以对结构体进行修改
func (u user) checkPassword(password string) bool{
}
func (u *user) checkPassword(password string) bool{
}
错误处理
在golang中,函数的错误处理放在了函数的返回值中
func findUser(id int)(v *user,err error){
if true{
return u,nil
}
return nil,eoors.New("error")
}
func main(){
u,err:=findUser(12)
if err!=nil{
xxx
}
}
字符串操作
在包 strings 里
var a string="hello"
strings.Contains(a,"ll") //true //判断是否包含
strings.Count(a,"l") // 2 判断子串数量
strings.HasPrefix(a,"he") // true 判断是否有前缀
strings.HasSuffix(a,"lo") // true 判断是否有后缀
strings.Index(a,"l") // 2 第一个该查询字符串的首字符index
strings.Join([]string{"hello","world"}," ") // 将数组中的字符串连接起来
strings.Repeat(a,2) // 字符串的重复
strings.Replace(a,"el","EL",-1) // -1 表示替换的位置不限制 字符串子串替换
strings.ToUpper(a)
strings.ToLower(a)
strings.Splite("a-b-c","-") // [a,b,c] 拆分字符串
len(a)
格式化输出
JSON操作
- 只要结构体中的变量名称都是大写字母开头就可以序列化为一个json,加json的tag后可以用小写表示。golang的tag用
`json:"age"`表示 - 可用string(json序列)来查看json序列。
- 解json的时候传递的是地址,其实也是他前边提到的,对于函数,想要改变变量的值,就一定要传他的地址,这算是golang的一个设计思想。
type userInfo struct {
Name string
Age int `json:"age"`
}
a := userInfo{
Name: "Jack",
Age: 0,
}
buf, err := json.Marshal(a)
if err != nil {
panic(err)
} else {
fmt.Println(string(buf))
}
var b userInfo
err = json.Unmarshal(buf, &b)
fmt.Println(b)
时间操作
// 最常见的时间使用方式,获取当前时间
time.Now()
// 构造一个时间
t := time.Date(2022, 12, 12, 12, 45, 56, 0, time.UTC)
fmt.Println(t)
// 可以获得其中的一个单独的part
var now time.Time = time.Now()
fmt.Println("Year=", now.Year())
// 时间减法获得一个时间段
diff := now.Sub(t)
fmt.Println(diff.Hours(), diff.Minutes(), diff.Seconds())
// 获取时间戳
fmt.Println(now.Unix())
字符串和数字之间的转换
// 字符串解析float,第二个参数表示位数
f, _ := strconv.ParseFloat("1.123", 64)
// 字符出啊解析int,第二个参数表示进制,第三个参数表示位数,第二个数字为0的话,会表示自己推断
i, _ := strconv.ParseInt("10", 10, 64)
fmt.Println(f, i)
// 数字转字符串
s, _ := strconv.Atoi("123")
s1, err := strconv.Atoi("AAA")
fmt.Println(s,s1, err)