字节后端青训学习第二篇

82 阅读5分钟

书接上回

基础语法

指针

代码示例:

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)
	add2ptr(&n)
	fmt.Println(n)
}

运行结果:

image.png

结构体

代码示例:

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)
	fmt.Println(checkPassword(a, "haha"))
	fmt.Println(checkPassword2(&a, "haha"))
}
func checkPassword(u user, password string) bool {
	return u.password == password
}
func checkPassword2(u *user, password string) bool {
	return u.password == password
}

运行结果:

image.png

结构体方法

代码示例:

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) {
	u.password = password
}
func main() {
	a := user{name: "wang", password: "1024"}
	a.resetPassword("2048")
	fmt.Println(a.checkPassword("2048"))
}

运行代码:

image.png

错误处理

错误处理 在 go 语言里面符合语言习惯的做法就是使用一个单独的返回值来传递错误信息。 不同于 Java 自家家使用的异常。go语言的处理方式,能够很清晰地知道哪个函数返回了错误,并且能用简单的 if else 来处理错误。

在函数里面,我们可以在那个函数的返回值类型里面,后面加一个 error, 就代表这个函数可能会返回错误。 那么在函数实现的时候, return 需要同时 return 两个值,要么就是如果出现错误的话,那么可以 return nil 和一个 error。如果没有的话,那么返回原本的结果和 nil。 代码示例

package main

import (
	"errors"
	"fmt"
)

type user struct {
	name     string
	password string
}

func findUser(user []user, name string) (v *user, err error) {
	for _, u := range user {
		if u.name == name {
			return &u, nil
		}
	}
	return nil, errors.New("not found")
}
func main() {
	u, err := findUser([]user{{"wang", "1024"}}, "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)
		return
	} else {
		fmt.Println(u.name)
	}
}

运行代码:

image.png

字符串操作

关于字符串的操作可以查看这篇文章GO常用标准库-strings - 知乎 (zhihu.com) 示例代码:

package main

import (
	"fmt"
	"strings"
)

func main() {
	a := "hello"
	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))
	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))
	fmt.Println(len(a))
	b:="你好"
	fmt.Println(len(b))
}

运行代码:

image.png

字符串格式化

字符串格式化。在标准库的 FMT 包里面有很多的字符串格式相关的方法,比如 printf 这个类似于 C 语言里面的 printf 函数。不同的是,在go语言里面的话,你可以很轻松地用 %v 来打印任意类型的变量,而不需要区分数字字符串。你也可以用 %+v 打印详细结果,%#v 则更详细。 示例代码

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.141592653
	fmt.Println(f)
	fmt.Printf("%.2f\n",f)
}

运行代码

image.png

json处理

下面我们来看一下+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)
	fmt.Println(string(buf))

	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)
}

代码运行:

image.png

时间处理

下面是时间处理,在go语言里面最常用的就是 time.now() 来获取当前时间,然后你也可以用 time.date 去构造一个带时区的时间,构造完的时间。上面有很多方法来获取这个时间点的年月日小时分钟秒,然后也能用点 sub 去对两个时间进行减法,得到一个时间段。时间段又可以去得到它有多少小时,多少分钟、多少秒。在和某些系统交互的时候,我们经常会用到时间戳。那您可以用 .UNIX 来获取时间戳。time.format time.parse 代码:

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now)
	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)
	fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())
	fmt.Println(t.Format("2006-01-02 15:04:05"))
	diff := t2.Sub(t)
	fmt.Println(diff)
	fmt.Println(diff.Minutes(), diff.Seconds())
	t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
	if err != nil {
		panic(err)
	}
	fmt.Println(t3 == t)
	fmt.Println(now.Unix())
}

运行代码:

image.png

数字解析

下面我们来学习一下字符串和数字之间的转换。在 go 语言当中,关于字符串和数字类型之间的转换都在 STR conv 这个包下,这个包是 string convert 这两个单词的缩写。我们可以用 parseInt 或者 parseFloat 来解析一个字符串。 parseint 参数我们可以用 Atoi 把一个十进制字符串转成数字。可以用 itoA 把数字转成字符串。如果输入不合法,那么这些函数都会返回error

package main

import (
	"fmt"
	"strconv"
)

func main() {
	f, _ := strconv.ParseFloat("1.234", 64)
	fmt.Println(f)

	n, _ := strconv.ParseInt("111", 10, 64)
	fmt.Println(n)

	n, _ = strconv.ParseInt("0x1000", 0, 64)
	fmt.Println(n)

	n2, _ := strconv.Atoi("123")
	fmt.Println(n2)

	n2, err := strconv.Atoi("AAA")
	fmt.Println(n2, err)
}

代码运行:

image.png

进程信息

在 go 里面,我们能够用 os.argv 来得到程序执行的时候的指定的命令行参数。比如我们编译的一个 二进制文件,command。 后面接 abcd 来启动,输出就是 os.argv 会是一个长度为 5 的 slice ,第一个成员代表二进制自身的名字。我们可以用 so.getenv来读取环境变量。exec 代码:

package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	fmt.Println(os.Args)

	fmt.Println(os.Getenv("path"))
	fmt.Println(os.Setenv("AA", "BB"))

	buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()

	if err != nil {
		panic(err)
	}
	fmt.Println(string(buf))
}

代码运行结果:

image.png

总结

经过今天的学习,终于将golang的基础内容全部大致的写完了,在学习过程中也找到了许多的不足,然后通过网上查阅把不懂的内容全部给补充回来了。