Go的基础语法(下) | 青训营笔记

86 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

Go学习笔记

Go的基础语法(下)

指针

Go中指针的功能没有C中那么强大,一般仅用于修改源数据的值

func add(n int) {
   n += 2
}

func add2(n *int) {
   *n += 2
}

n := 5
add2(n)
// 在调用的时候要加上&
add2(&n)

结构体

结构体应该就是相当与其他面向编程语言中的类,当一个普通方法把第一个参数提到前面,这个方法就属于一个结构体方法

type user struct {
   username string
   password string
}
// 普通方法
func checkPassword(u user, password string) bool {
   return u.password == password
}
// 结构体方法
func (u user) checkPassword(password string) bool {
   return u.password == password
}

异常处理

可以通过errors.New()创建一个异常信息,然后可以被if捕获到

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{
    if u, err := findUser([]user{{"zeniein", "1024"}}, "wang"); err != nil {
       fmt.Println(err)
    } else {
       fmt.Println(u.name)
    }
}

字符串常用操作

ps:在字符串中汉字的长度不是1

a := "hello"
// 是否包含子串"ll"
fmt.Println(strings.Contains(a, "ll"))
// 出现数量
fmt.Println(strings.Count(a, "l"))
// 是否以该子串作为前缀
fmt.Println(strings.HasPrefix(a, "he"))
// 是否以该子串作为后缀
fmt.Println(strings.HasSuffix(a, "llo"))
// 出现该子串的索引位置
fmt.Println(strings.Index(a, "ll"))
// 将一个字符串数组用该字符串相连接成单个字符串
fmt.Println(strings.Join([]string{"he", "llo"}, "-"))
// 字符串重复
fmt.Println(strings.Repeat(a, 2))
// 替换子串,第一个参数表示要操作的字符串
// 第二个表示旧值
// 第三个为新值
// 第四个为限制替换的个数,小于0表示不限制
fmt.Println(strings.Replace(a, "e", "E", -1))
// 将字符串按所所给的字符进行切片
fmt.Println(strings.Split("a-b-c", "-"))
// 转为小写
fmt.Println(strings.ToLower(a))
// 转为大写
fmt.Println(strings.ToUpper(a))

格式化

可以通过格式化输出不同详细程度的信息,在数据格式化中最常见的就是浮点数保留两位小数

type point struct {
   x, y int
}
func main(){
    p := point{1, 2}
    fmt.Println(p) // {1 2}
    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.Println(f) // f := 3.141592653
   fmt.Printf("%.2f", f) // 3.14
}

JSON序列化和反序列化

Go自带有JSON序列化和反序列化,其他语言一般都需要引入第三方

使用自带的JSON序列化需要保证属性字段首字母大写,不然就需要添加标签告诉程序该按什么格式进行解析

type userInfo struct {
   Name  string
   Age   int `json:"age"`
   Hobby []string
}

a := userInfo{Name: "zeniein", Age: 18, Hobby: []string{
    "Golang",
    "Java",
    "TypeScript",
}}

json.Marshal和json.MarshalIndent都可以实现对象的JSON序列化

buf, err := json.Marshal(a)
if err != nil {
    panic(err)
}
fmt.Println(string(buf))
// 输出
{"Name":"zeniein","age":18,"Hobby":["Golang","Java","TypeScript"]}

buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
    panic(err)
}
fmt.Println(string(buf))
// 输出
{

        "Name": "zeniein",
        "age": 18,
        "Hobby": [
                "Golang",
                "Java",
                "TypeScript"
        ]
}

使用json.Unmarshal进行反序列化

var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
    panic(err)
}
fmt.Printf("%#v\n", b)
// main.userInfo{Name:"zeniein", Age:18, Hobby:[]string{"Golang", "Java", "TypeScript"}}

时间格式化

Go时间格式化不像其他语言使用'yyyy-MM-dd HH:mm:ss'这样进行格式化,而是通过特定的一些值,这些值可以在官方文档中可以找到,不然的话它会逐字回显导致时间不能正常格式化

2023-01-15_205120.png

t := time.Date(2023, 1, 15, 12, 25, 36, 0, time.UTC)
// 2023 January 15 12 25
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())
// 2023-01-15 12:25:36
fmt.Println(t.Format("2006-01-02 15:04:05"))

t3, err := time.Parse("2006-01-02 15:04:05", "2023-01-15 12:25:36")
if err != nil {
    panic(err)
}
// 2023-01-15 12:25:36
fmt.Println(t3)

字符串转换

使用了strconv这个标准库进行字符串的转化

f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f) // 1.234

n, _ := strconv.ParseInt("111", 10, 64)
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

每门编程语言都有共通性,也有差异性,如果之前接触其他语言的话,当学习一门新的编程语言的时候可能因为一些这门语言的一些与众不同的点跟之前学的语言有点差别,可能会带来一点小冲击,但慢慢去接受它,这一切都会很会很美好!Happy Coding!