1.基础语法-map
在其他编程语言中,它可能叫做哈希或者字典。 map是实际使用过程中频繁用到的数据结构。 如下边代码可以使用make创建一个空map,这里会需要两个类型,第一个是那个key的类型string,另一个是value的类型int. 我们可以从里边存储或取出键值对。可以用delete从里面删除键值对。 golang的map是完全无序的,遍历的时候不会按照字母顺序,也不会按照插入顺序输出,而是随机顺序。
package main
import "fmt"
func main(){
m:=make(map[string]int)
m["one"]=1
m["two"]=2
fmt.Println(m) //map[one:1 two 2]
fmt.Println(len(m)) //2
fmt.Println(m["one"]) //1
fmt.Println(m["unknow"]) //0
r,ok=m["unknow"]
fmt.Println(m,"unkonw") //0 false
delete(m,"one") //删除字典中某个键
m2:=map[string]int{"one":1,"two":2}
var m3=map[string]int{"one":1,"two:2}
fmt.Println(m2,m3)
}
2.基础语法-range
对于一个slice或者一个map的话,我们可以用range来快速遍历,这样代码能够更加简洁。 range遍历的时候,对于数组会返回两个值,第一个是索引,第二个是对应位置的值。如果我们 不需要索引的话,我们可以用下划线来忽略。
package main
import "fmt"
func main(){
nums:=[]int{2,3,4}
sum:=0
for i, num :=range nums{
sum+=num
if num==2{
fmt.Println("index:"i,"num:",num)
}
}
fmt.Println(sum) //9
m:=map[string]string{"a":"A","b":"B"}
for k,v:=range m{
fmt.Println(k,v) // b B;a A
}
for k:=range m{
fmt.Println("key",k) //key a; key b
}
}
3.基础语法-函数
下边代码展示的是Golang里面一个简单的实现两个变量相加的函数。Golang和其他 很多语言不一样的是,变量类型是后置的。 Golang里面的函数原生支持返回多个值,第一个是真正的返回结果,第二个值是一个错误信息。
package main
import "fmt"
func add(a int,b int)int{
return a+b
}
func add2(a,b int)int{
return a+b
}
func exists(m map[string]string,k string)(v string,ok bool){
v,ok=m[k]
return v,ok
}
func main(){
res:=add(1,2)
fmt.Println(res) //3
v,ok:=exists(map[string]string{"a":"A"},"a")
fmt.Println(v,ok) //A True
}
4.基础语法-指针
go里面也支持指针。当然相比C和C++里面的指针,支持的操作很有限。指针的一个主要用途就是对传入参数进行修改。 我们来看下边这个函数,这个函数试图把一个变量+2,但是单纯这种写法是无效的。因为传入函数的参数实际上是一个拷贝,即就是对那个拷贝进行了加2,并不起作用。如果我们需要起作用的话,那么我们需要把那个类型写成指针类型,为了类型匹配,调用的时候会加一个&符号。
package main
import "fmt"
func add2(n int){
n+=2
}
func add2ptr(n *int){
*n+=2
}
func main(){
n:=5
add2(n)
fmt.Println(n) //5
add2ptr(&n)
fmt.Println(n) //7
}
5.基础语法-结构体
结构体是带类型的字段的集合。 如下面user结构包含了两个字段,name和password。我们可以用结构体的名称去初始化一个结构体变量,构造的时候需要传入每个字段的初始值,也可以用这种键值对的方式去指定初始值,这样只对一部分字段进行初始化。同样结构体也能支持指针,这样能够实现对于结构体的修改,也可以·在某些情况下避免一些大结构体的拷贝开销。
package main
import "fmt"
type user struct{
name string
password string
}
func main(){
a:=user{name:"wang",password:"1024"}
b:=user{"wang","1024"}
c:=user{name:"wang"}
c.password="1024"
var d user
d.name="wang"
d.password="1024"
fmt.Println(a,b,c,d)//{wang 1024} {wang 1024} {wang 1024} {wang 1024}
fmt.Println(checkPassword(a,"haha") //false
fmt.Println(checkPassword2(&a,"haha") //false
}
func checkPassword(u user,password string)bool{
return u.password==password
}
func checkPassword2(u *user,password string)bool{
return u.password==password
}
6.基础语法-结构体方法
在Golang里面可以为结构体去定义一些方法。 在实现结构体方法的时候也有两种写法,一种是带指针,一种是不带指针。这个区别是如果带指针可以对这个结构体进行修改。如果不带指针的话,那么实际上操作的是一个拷贝,你就无法对结构体进行修改。
package main
import "fmt"
type user struct{
name string
password string
}
func (u user)checkPassword(password string)bool{
return u.password==password
}
func (u *user)resetPassword(password string)bool{
return u.password==password
}
func main(){
a:=user{name:"wang",password:"1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2038")) //true
}
7.基础语法-错误处理
错误处理在go语言里面符合语言习惯的做法就是使用一个单独的返回值来传递错误信息。 go语言的处理方式,能够清晰地知道那个函数返回了错误,在函数里面,我们可以在那个函数的返回值类型里面,后面加一个error,就代表这个函数可能会返回错误。 那么在函数实现的时候,return需要同时return两个值,那么就是如果出现错误的话,那么可以return nil和一个error.如果没有的话,那么返回原本的结果和nil。
package main
import(
"errors"
"fmt"
)
type user struct{
name string
password string
}
func findUser(users []user,name string)(v *user,err error){
for _,u:=range users{
if u.name==name{
return &u,nil
}
}
return nil,errors.New("not found")
}
func main(){
u,err:=findUser([]{{"wang","1024"}},"wang")
if err!=nil{
fmt.Println(err)
return
}
fmt.Println(u.name) //wang
if u,err:=findUser([]user{{"wang","1024"},"li"};err!=nil{
fmt.Println(err) //not found
return
}else{
fmt.Println(u.name)
}
}
8.基础语法-字符串操作
在标准库strings包里面有很多常用的字符串工具函数,比如contains判断一个字符串里面是否 包含另一个字符串,count字符串计数,index判断某个字符串位置。 join连接多个字符串,repeat重复多个字符串,replace替换字符串。
package main
import(
"fmt"
"strings"
)
func main(){
a:="hello"
fmt.Println(strings.Contain(a,"ll")) //true
fmt.Println(strings.Count(a,"l")) //2
fmt.Println(strings.HasPrefix(a,"he")) //true
fmt.Println(strings.HasSuffix(a,"llo")) //true
fmt.Println(strings.Index(a,"ll")) //2
fmt.Println(strings.Join([]string{"he","llo"},"-")) //he-llo
fmt.Println(strings.Repeat(a,2)) //hellohello
fmt.Println(strings.Replace(a,"e","E",-l)) //hEllo
fmt.Println(strings.Split("a-b-c","-")) //[a,b,c]
fmt.Println(strings.ToLower(a)) //hello
fmt.Println(strings.TOUpper(a)) //HELLO
fmt.Println(len(a)) //5
b:="你好"
fmt.Println(len(b)) //6
}
9.基础语法-字符串格式化
go语言里的printf类似于c语言里面的printf函数,不同的是,在go语言里面的话, 你可以很轻松地用%v来打印任意类型的变量,而不需要区分数字字符串。你也可以用%+v来打印详细结果,%#v则更详细。
package main
import main
type point struct{
x,y int
}
func main(){
s:="hello"
n:=123
p:=point{1,2}
fmt.Println(s,n) //hello 123
fmt.Println(p) //{1,2}
fmt.Printf("s=%v\n",s) //s=hello
fmt.Printf("n=%v\n",s) //n=123
fmt.Printf("p=%v\n",p) //p={1 2}
fmt.Printf("p=%+v\n",p) //p={x:1 y:2}
fmt.Printf("p=%#v\n",P) //p=main.point{x:1,y:2}
f:=3.141592653
fmt.Printf(f) //3.141592653
fmt.Printf("%.2f\n",f) //3.14
}
10.基础语法-JSON处理
go语言 里面的 JSON 操作非常简单,对于一个已有的结构体,我们可以什么都不做,只要保证每个字段的第一个字母是大写,也就是是公开字段。那么这个结构体就能用 JSON.marshaler 去序列化,变成一个JSON 的字符串。 序列化之后的字符串也能够用JSON.unmarshaler 去反序列化到一个空的变量里面。 这样默认序列化出来的字符串的话,它的风格是大写字母开头,而不是下划线。我们可以在后面用 json tag 等语法来去修改输出 JSON 结果里面的字段名。
package main
import (
"encoding/json"
"fmt"
)
type userInfo struct{
Name string
Age int `json:"age"`
Hobby []string
}
func main(){
a:=userInfo{Name:"wang",Age:18,Hobby:[]string{"Golang","TypeScript"}}
buf,err:=json.Marshal(a)
if err!=nil{
panic(err)
}
fmt.Println(buf) //[123 34 78 97...]
fmt.Printn(string(buf))//{"Name":"wang","age":18,"Hobby":{"Golang","TypeScript"}}
buf,err=json.MarshalIndent(a,"","\t")
if err!=nil{
panic(err)
}
fmt.Println(string(buf))
var b userInfo
err=json.Unmarshal(buf,&b)
if err!=nil{
panic(err)
}
fmt.Printf("%#v\n",b)//main.userinfo{Name:"wang",Age:18,Hobby:[]string{"Golang","TypeScript"}}
}
11.基础语法-时间处理
下面是时间处理,在go语言里面最常用的就是 time.now()来获取当前时间,然后你也可以用 time.date 去构造一个带时区的时间,构造完的时间。上面有很多方法来获取这个时间点的年月日小时分钟秒,然后也能用点 sub 去对两个时间进行减法,得到一个时间段。时间段又可以去得到它有多少小时,多少分钟、多在和某些系统交互的时候,我们经常会用到时间戳。那您可以用 .UNIX 来获取时间戳。
package main
import(
"fmt"
"time"
)
func main(){
now:=time.Now()
fmt.Println(now) //2022-03-27 18:04:59.433297 +0800 CST m=+0.000087933
t:=time.Date(2022,3,27,1,25,36,0,time.UTC)
t2:=time.Date(2022,3,27,2,30,36,0,time.UTC)
fmt.Println(t) //2022-03-27 1:25:36 +0000 UTC
fmt.Println(t.Year(),t.Month(),t.Day(),t.Hour(),t.Minute())//2022 March 27 1 25
fmt.Println(t.Format("2006-01-02 15:04:05")) //2022-03-27 01:25:36
diff:=t2.Sub(t)
fmt.Println(diff) //1h5m0s
fmt.Println(diff.Minutes(),diff.Seconds()) //65 3900
t3,err:=time.Pares("2006-01-02 15:04:05","2022-03-27 01:25:36")
if err!=nil{
panic(err)
}
fmt.Println(t3==t) //true
fmt.Println(now.Unix())//1648738080
}
12.基础语法-数字解析
在 go 语言当中,关于字符串和数字类型之间的转换都在 STR conv 这个包地下,这个包是 string convert 这两个单词的缩写。我们可以用 parselnt 或者 parseFloat 来解析一个字符串。 parseint 参数 我们可以用 Atoi把一个十进制字符串转成数字。可以用 itoA 把数字转成字符串。如果输入不合法,那么这些函数都会返回error
package main
import(
"fmt"
"strconv"
)
func main(){
f,_:=strconv.ParseFloat("1.234",64)//字符串和浮点数之间的转换,
第一个参数为字符串,第二个参数为精度
fmt.Println(f) //1.234
n,_:=strconv.ParseInt("111",10,64)
//第一个参数为字符串,第二个参数为所需要的进制,2到32进制。
//第三个参数是限制位,如果超过2^63-1,那么err就会显示超出范围,输出n为2^63-1
fmt.Println(n) //111
n,_=strconv.ParseInt("0x1000",0,64)
fmt.Println(n) //4096
n2,_:=strconv.Atoi("123")
fmt.Println(n2)//123
n2,err:=strconv.Atoi("AAA")
fmt.Println(n2,err)// 0 strconv.Atoi : parsing "AAA":invalid syntax
}