Golang基础语法

87 阅读2分钟

省流不看版: 基础语法课程的笔记,可以说是毫无水平的教程照抄。

大部分操作都自己运行过,改了改参数什么的,Golang语法虽然有GPT老师,但自己写写还是最有用的学习方式,回想起了学期初一个月速成js+react去做项目网站的日子.......权当一个以后三天打鱼两天晒网查漏补缺巩固基础的笔记了。

变量类型

  • 字符串是内置类型,可直接通过“+”拼接
  • 变量声明
var a,b int = 1, 2
a,b := 1,2   // := 声明更简洁,可读性强

f :=float32(e)

const s string = "constant"  //常量无确定类型,可根据使用上下文自己确定

if else

if 7%2 == 0 {
	fmt.Println("7 is even")  //条件没有括号,且必须跟大括号
}

唯一一种循环

for{
	fmt.Println("死循环")
	break
}

for j := 7; j < 9; j++ {  //任何一段都可以省略
	fmt.Println(j)
}

分支结构

switch a {  //不需要加break
case 1:
	fmt.Println("one")
case 2:
	fmt.Println("two")
case 3, 4:
	fmt.Println("three or four")
default:
	fmt.Println("other")
}

t := time.Now()    // case可以使用任意变量类型,包括字符串和结构体
switch {    //可以取代部分if else功能
case t.Hour() < 12:
	fmt.Println("It's before noon")	
default:
	fmt.Println("It's afternoon")
}

数组

var a [5]int   //存放5个int的数组
a[4] = 100
fmt.Println(a[4], len(a))

由于长度固定,业务中多用“切片”

切片

s := make([]string, 3)
s[0] = "a"
s[1] = "b"
fmt.Println(s[1]) // b

s= append(s, "c", "d")
fmt.Println(s)  // [a b  c d] //由于切片长度为3但只赋2个值,故空出一位

s[2] = "c"
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)  // [a b c d]

fmt.Println(s[1:3]) // [b c]

map

//map
m := make(map[string]int) //string:key类型  value类型:int
m["one"] = 1
m["two"] = 2
fmt.Println(m, len(m), m["two"], m["three"]) //map[one:1 two:2] 2 2 0

//删除map的k-v对
delete(m, "one")
fmt.Println(m, len(m), m["two"], m["three"]) //map[two:2] 1 2 0

range

//range 数组
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
	sum += num
	fmt.Println("index:", i, "num:", num) //index: 0 num: 2  index: 1 num: 3  index: 2 num: 4
}
fmt.Println(sum) // 9

//range map
maps := map[string]string{"a": "A", "b": "B"}
for k, v := range maps {
	fmt.Println(k, v)
}
for k := range maps {
	fmt.Println("key", k)
}

函数

// 函数:要写在func main()外部

func add(a int, b int) string {
    sum := a + b
    result := fmt.Sprintf("a+b的值是%d", sum)  
    return result
}

func exists(m map[string]string, k string) (v string, ok bool) {
    v, ok = m[k]
    return v, ok  
    // `ok` 是一个布尔型的返回值,一般用于判断某个操作是否成功完成,这里是检查value是否存在
}

func main(){
	aa, bb := 1, 2
    fmt.Println(add(1, 2))  // a+b的值是3
    
	testMap := map[string]string{"hello": "Hello", "world": "World"}
    fmt.Println(exists(testMap, "hello"))  // Hello true
    fmt.Println(exists(testMap, "hi")) // false
    fmt.Println(exists(testMap, "world")) // World true
}

指针

func add2(n int) {
    n += 2  //这里操作的其实是n的副本,不会对原变量进行修改
}

func add2ptr(n *int) {
    *n += 2   //指针就可以对原变量进行修改
}

func main() {
    ptr := 5
    add2(ptr)
    fmt.Println(ptr) // 5
    add2ptr(&ptr)   //注意要加&取地址符,获取一个变量的指针
    fmt.Println(ptr) // 7

结构体 大类型字段的集合

type user struct {
    name     string
    password string
}

user_a := user{name: "wang", password: "1024"}
user_b := user{"wang", "1024"}
user_c := user{name: "wang"}
fmt.Println(user_a, user_b, user_c)  // {wang 1024} {wang 1024} {wang }
user_c.password = "1024"
d := user{} // var d user
d.name = "wang"
d.password = "1024"
fmt.Println(d)   //{wang 1024}
fmt.Println(&user_a) //&{wang 1024}


struct_ptr_A := &user_a
fmt.Println("name:", struct_ptr_A.name)  // name: wang
fmt.Println("name:", user_b.name)  // name: wang1
struct_ptr_A.password = "1234"
fmt.Println("修改后的A用户信息:", user_a)  // 修改后的A用户信息: {wang 1234}

结构体方法

func (u user) checkPassword(password string) bool {
    return u.password == password
}

func (u *user) resetPassword(password string) {  //带指针可对结构体进行修改
    u.password = password
}

//结构体方法
user_test := user{name: "zhang", password: "4321"}
fmt.Println("original password:", user_test.password)  // original password: 4321
user_test.resetPassword("1234")
fmt.Println("new password:", user_test.password)  // new password: 1234
fmt.Println(user_test.checkPassword("1234"))  // true

错误处理

func findUsers(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")
}

//错误处理
u, err := findUsers([]user{{"wang", "1024"}}, "wang")
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(u.name)

if u, err := findUsers([]user{{"wang", "1024"}}, "li"); err != nil {
	fmt.Println(err)  // wang
	return
} else {
	fmt.Println(u.name)  // not found
}

字符串操作

str_a := "hellolL"

fmt.Println(strings.Contains(str_a, "ll"))            // true
fmt.Println(strings.Count(str_a, "l"))                // 4
fmt.Println(strings.HasPrefix(str_a, "he"))           // 判断字符串 str_a 是否以 he 开头
fmt.Println(strings.HasSuffix(str_a, "llo"))          // 判断字符串 str_a 是否以 llo 结尾
fmt.Println(strings.Index(str_a, "ll"))               // 2
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) //  he-llo
fmt.Println(strings.Repeat(str_a, 2))                 // hellollhelloll
fmt.Println(strings.Replace(str_a, "l", "L", -1))     // heLLoLL   "-1"表示替换旧字符串次数,这里是替换所有
fmt.Println(strings.Split("a-b--c", "-"))             // [a b  c]
fmt.Println(strings.ToLower(str_a))                   // helloll
fmt.Println(strings.ToTitle(str_a))                   // HELLOLL
fmt.Println(len(str_a))                               // 7

字符串格式化

  • %d 用于输出十进制整数的值,例如  fmt.Printf("%d", 42) 将输出 42
  • %v 用于输出值的默认格式,例如 fmt.Printf("%v", "hello") 将输出 "hello",而 fmt.Printf("%v", 42) 将输出 42
  • %s 用于输出字符串的值,例如 fmt.Printf("%s", "hello") 将输出 "hello"。 除了这些常用的占位符之外,Go 语言还提供很多其他类型的占位符,如 %f 用于输出浮点数, %p 用于输出指针地址等。

JSON处理

  • encoding/json 包可以实现 JSON 编码和解码
  • 使用 json.Marshal() 函数将 Go 中的数据类型编码为 JSON 字节数组
  • 使用 json.MarshalIndent() 函数将 Go 中的数据类型编码为缩进格式的 JSON 字节数组
  • 使用 json.Unmarshal() 函数将 JSON 字节数组解码为 Go 数据类型
  • 在 JSON 编码和解码过程中,需要使用字节数组或字符串储存 JSON 数据

时间处理

// 创建时间对象并输出

now := time.Now()
fmt.Println("当前时间:", now)

// 使用时间常量并输出

delay := 3 * time.Second
fmt.Printf("延迟 %s 后执行任务...\n", delay)

// 时间延迟

time.Sleep(delay)
fmt.Println("任务执行中...")

// 时间格式化

t1 := time.Date(2022, time.May, 3, 10, 34, 0, 0, time.Local)
fmt.Println("时间格式化:", t1.Format("2006-01-02 15:04:05"))

// 时间定时器

fmt.Println("启动定时器...")
timer := time.NewTimer(5 * time.Second)
<-timer.C
fmt.Println("定时器时间到...")

timer.C 是一个类型为 <-chan time.Time(只能从通道中读取)的通道,表示定时器到期的时间。在定时器到期前,该通道会一直阻塞等待,直到定时器到期,通道中会发送一个时间事件给它的接收者。

Parse 函数适用于将时间字符串转换为 time.Time 类型,常用于从输入中解析年月日等日期信息。例如:

dateString := "2022-07-28"
fmt.Println(time.Parse("2006-01-02", dateString)) //2022-07-28 00:00:00 +0000 UTC <nil>

Unix 函数适用于将 Unix 时间戳(自 1970 年 1 月 1 日 00:00:00 UTC 起的秒数)转换为时间对象,或将时间对象转换为 Unix 时间戳。例如:

timestamp := int64(1659729852)
fmt.Println(time.Unix(timestamp, 0))  // 2022-08-06 04:04:12 +0800 CST

now := time.Now()
fmt.Println(now.Unix())  // 1683998108

Format 函数适用于将时间对象格式化为字符串,常用于将时间对象转换为易于读取的字符串。例如:

t2 := time.Date(2022, time.August, 1, 12, 0, 0, 0, time.UTC)
fmt.Println(t2.Format("2006-01-02 15:04:05"))   // 2022-08-01 12:00:00

数字解析

strconv.ParseFloat 方法用于将字符串转换为 float64 类型的数值 strconv.ParseInt方法用于将字符串转换为指定进制下的 int64 类型的数值 strconv.Atoi方法用于将字符串转换为十进制下的 int 类型的数值

n1, err := strconv.Atoi(("AAA"))
fmt.Println(n1, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax

n2, err := strconv.Atoi("123")
fmt.Println(n2, err) // 123 <nil>

进程信息

fmt.Println(os.Args)
fmt.Println(os.Getenv("PATH")) // 获取环境变量
fmt.Println(os.Setenv("AA", "BB")) // 设置环境变量

os.Command用于执行一个指定的命令。该函数会返回一个 *exec.Cmd 类型的指针,该指针包含了与执行命令相关的属性和方法,例如命令行参数、标准输入、标准输出、执行状态等。