1.go语言基础语法
1.1 point 指针
指针的主要用途是对传入的参数进行修改,下面第14到16行的函数试图将变量a加2,但这种写法实际上是无效的,这种传递参数是值的拷贝。有效做法是将传入的变量定义为指针类型,并在调用函数时使用相匹配的变量类型。
package main
import (
"fmt"
)
func main() {
a := 5
add(a)
fmt.Println(a)
addptr(&a)
fmt.Println(a)
}
func add(a int) {
a = a + 1 //
}
func addptr(a *int) {
*a = *a + 1
}
1.2 struct 结构体
结构体是带类型的字段的集合,可以用结构体的名称初始化结构体变量,在初始化的时候需要传入每个字段的值。结构体也能作为函数的参数,有指针和非指针两种用法,用指针的话,可以实现对结构体的修改,某些情况下也能避免大结构体的开销。
package main
import (
"fmt"
)
type user struct {
name string
password string
}
func main() {
a := user{name: "wang", password: "123456"}
b := user{name: "fan"}
c := user{"fan", "1024"}
var d user
d.name = "Liu"
d.password = "123456"
fmt.Println(a, b, c, d)
fmt.Println(checkPassword(a, "hahahahaha"))
checkPassword2(&a, "hhhh")
fmt.Println(a)
}
func checkPassword(a user, password string) bool {
return a.password == password
}
func checkPassword2(a *user, password string) {
a.password = password
}
1.3 struct-method 结构体函数
在goland里面可以用结构体去定义一些方法,这会非常类似其它语言的类成员函数。
package main
import (
"fmt"
)
type user struct {
name string
password string
}
func main() {
a := user{name: "wang", password: "123456"}
b := user{name: "fan"}
c := user{"fan", "1024"}
var d user
d.name = "Liu"
d.password = "123456"
fmt.Println(a, b, c, d)
fmt.Println(a.checkPassword("hahahahaha"))
a.resetPassword("hahahahaha")
fmt.Println(a.checkPassword("hahahahaha"))
}
func (a user) checkPassword(password string) bool {
return a.password == password
}
func (a *user) resetPassword(password string) {
a.password = password
}
1.4 错误处理
在goland里面符合语言错误处理的习惯是使用单独的返回值来传递错误信息,不同于java里面使用的异常机制,go语言的处理方式能够很清晰的知道那个函数返回了错误,而且能够用简单的if,else去处理错误。我们可以在函数的返回值里加上一个error,代表函数可能出现错误。
package main
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
func main() {
u, err := findUser([]user{{"wang", "1234"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name)
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // not found
return
} else {
fmt.Println(u.name)
}
}
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")
}
1.5 字符串操作
在标准库strings包里面有非常多的字符串工具函数。
ackage main
import (
"errors"
"fmt"
"strings"
)
type user struct {
name string
password string
}
func main() {
a := "heello"
fmt.Println(strings.Contains(a, "ll")) //判断a中是否包含字符
fmt.Println(strings.Count(a, "l")) //计算a中包含字符的个数
fmt.Println(strings.HasPrefix(a, "he")) //判断a中是否包含前缀
fmt.Println(strings.HasSuffix(a, "llo")) //判断a中是否包含后缀
fmt.Println(strings.Index(a, "ll")) //计算a中字符的下标
fmt.Println(strings.Join([]string{"he", "llo"}, "")) //将两个字符串通过字符连接起来
fmt.Println(strings.Repeat(a, 2)) //复制n次字符串
fmt.Println(strings.Replace(a, "e", "E", 1)) //替换a中的n个字符
fmt.Println(strings.Split("a-b-c", "-")) //通过指定字符分割字符串
fmt.Println(strings.ToLower(a)) //将字符串中的字符变成小写字符
fmt.Println(strings.ToUpper(a)) //将字符串中的字符变成大写字符
fmt.Println(len(a)) //计算字符长度
}
1.6 字符串格式化
在标准库的fmt包里面有非常多的字符串格式化的相关方法,最常用的如下面的代码所示。
package main
import (
"fmt"
)
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n)
fmt.Println(p)
fmt.Printf("s=%v\n", s)
fmt.Printf("n=%v\n", n)
fmt.Printf("p=%v\n", p)
fmt.Printf("p=%+v\n", p)
fmt.Printf("p=%#v\n", p)
f := 3.1415926
fmt.Printf("%.2f\n", f)
}
1.7 json处理
goland里的json处理非常简单,只需要在结构体中每个字段首字母大写,那么这个结构体就能够序列化,序列化后的字符串也可以进行反序列化,具体操作如下所示。
package main
import (
"encoding/json"
"fmt"
)
type userInfo struct {
Name string `json:"name"`
Age int `json:"age"`
Hobby []string `json:"hobby"`
}
func main() {
a := userInfo{"WangGang", 18, []string{"Goland", "Python", "Java"}}
buf, err := json.Marshal(a)
if err != nil {
println(err)
}
fmt.Println(buf)
fmt.Println(string(buf))
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
println(err)
}
fmt.Println(buf)
fmt.Println(string(buf))
var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b)
}
1.8 时间处理
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Println(now)
t1 := time.Date(2022, 7, 12, 14, 30, 25, 0, time.UTC)
t2 := time.Date(2022, 3, 28, 11, 25, 36, 0, time.UTC)
fmt.Println(t1)
fmt.Println(t2.Year(), t2.Month(), t2.Day(), t2.Hour(), t2.UTC())
fmt.Println(t1.Format("2006-01-02 15:04:05"))
diff := t2.Sub(t1)
fmt.Println(diff)
fmt.Println(diff.Minutes(), diff.Seconds())
t3, err := time.Parse("2006-01-02 15:04:05", "2022-07-12 14:30:25")
if err != nil {
panic(err)
}
fmt.Println(t3 == t1) // true
fmt.Println(now.Unix()) // 1648738080
}
1.9 数字解析
- ParseInt函数 func ParseInt(s string, base int, bitSize int) (i int64, err error) 返回字符串表示的整数值,接受正负号。 base指定进制(2到36),如果base为0,则会从字符串前置判断,"0x"是16进制,"0"是8进制,否则是10进制;bitSize指定结果必须能无溢出赋值的整数类型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64;返回的err是*NumErr类型的,如果语法有误,err.Error = ErrSyntax; 如果结果超出类型范围err.Error = ErrRange。
- Atoi函数 func Atoi(s string) (i int, err error) Atoi是ParseInt(s, 10, 0)的简写
package main
import (
"fmt"
"strconv"
)
func main() {
f, _ := strconv.ParseFloat("1.345", 64)
fmt.Println(f)
n, _ := strconv.ParseInt("111", 10, 64)
fmt.Println(n)
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) // 4096
n2, _ := strconv.Atoi("123")
fmt.Println(n2) // 123
n3, err := strconv.Atoi("AAA")
fmt.Println(n3, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax
}