走进Go语言基础语法 | 青训营

56 阅读6分钟

走进Go语言基础语法 | 青训营

01简介

1.1 什么是Go语言:

  1. 高性能,高并发;
  2. 语法简单,学习曲线平缓;
  3. 丰富的标准库;
  4. 完善的工具链;
  5. 静态链接;
  6. 快速编译;
  7. 跨平台;
  8. 垃圾回收;

补充:

Go语言是一种开源的静态类型、编译型编程语言,由Google公司于2007年开始设计和开发,并于2009年正式发布。Go语言的设计目标是提供一种简洁、高效、可靠的编程语言,以解决大规模软件开发中的一些痛点和挑战。

Go语言的特点包括:

  1. 简洁易读:Go语言的语法简洁清晰,代码易于阅读和理解。它摒弃了一些冗余的语法和复杂的特性,使得代码更加简洁明了。
  2. 高效编译:Go语言的编译速度非常快,可以在几秒钟内完成大部分程序的编译。这使得开发者可以迅速地进行代码测试和迭代。
  3. 并发编程:Go语言内置了轻量级的并发机制,使用goroutine和channel可以方便地进行并发编程。这使得编写高效的并发程序变得更加简单和直观。
  4. 内存安全:Go语言具有垃圾回收机制,自动管理内存,减少了开发者对内存管理的负担。它还提供了一些安全机制,如切片越界检查和空指针检查,可以有效避免一些常见的内存安全问题。
  5. 跨平台支持:Go语言的编译器可以将Go代码编译成机器码,支持多种操作系统和硬件平台。这使得开发者可以在不同的平台上开发和部署Go程序。
  6. 生态丰富:Go语言拥有丰富的标准库和第三方库,涵盖了各种常用的功能和工具。开发者可以方便地使用这些库来加速开发过程。

Go语言被广泛应用于云计算、网络编程、分布式系统、大数据处理等领域。它已经成为一种受欢迎的编程语言,并得到了许多开发者和企业的认可和采用。

1.2有哪些公司在使用Go语言:

例如:字节跳动,腾讯,美团,滴滴,百度等等公司

1.3字节跳动为什么全面使用Go语言:

  1. 最初使用的 Python,由于性能问题换成了Go
  2. C++不太适合在线Web 业务
  3. 早期团队非Java背景
  4. 性能比较好
  5. 部署简单、学习成本低
  6. 内部 RPC和HTTP框架的推广

02入门

2.1 开发环境:

2.1.1安装Golang

下载网址:

  1. go.dev/
  2. studygolang.com/dl
  3. goproxy.cn/

2.1.2配置集成开发环境:

2.1.3基于云的开发环境:

  1. gitpod.io/#github.com…
  2. 短链接:hi-hi.cn/gitpod

2.2 基础语法:

2.2.1 Hello World:

package main
​
import (
    "fmt"
)
​
func main() {
    fmt.Println("Hello World")
}
​

这段代码是一个简单的Go语言程序,用于"Hello World"。代码主要包含主函数 main()。程序在主函数中调用 fmt 包中的 Println 函数来打印字符串 "Hello World" 到控制台。 在执行该程序时,会在控制台输出 "Hello World"。 这段代码的作用是打印一条简单的问候语,用于验证Go语言环境是否正常安装和配置。

2.2.2 变量:

package main
​
​
import(
    "fmt"
    "math"
)
​
func main() {
    var a = "inital"
    var b, c int = 1, 2
    var d = true
    var e float64
    f :=float32(e)
​
    g := a + "foo"
    fmt.Println(a,b,c,d,e,f)
    fmt.Println(g)
​
    const s string = "constant"
    const h  =500000000
    const i = 3e20/h
    fmt.Println(s,h,i,math.Sin(h),math.Sin(i))
}

这段代码是一个Go语言程序,包含了变量声明、赋值、类型推断、常量定义和使用,以及一些数学函数的调用。 代码中的变量声明包括了字符串类型的变量 a,整数类型的变量 bc,布尔类型的变量 d,以及浮点数类型的变量 ef。 变量 a 被初始化为字符串 "inital"。变量 b 被初始化为整数值 1,变量 c 被初始化为整数值 2。变量 d 被初始化为布尔值 true。 变量 e 被声明为一个浮点数类型的变量,但未被初始化。接着,变量 f 使用 := 简略赋值语法来推断其类型为浮点数类型,并将其值设置为 e 的类型转换为 float32 后的值。 变量 g 通过将变量 a 与字符串 "foo" 进行拼接而得到。 程序中还定义了一些常量,包括一个字符串常量 s,一个整数常量 h,和一个通过数学运算得出的常量 i。然后通过调用 math.Sin() 函数计算了 hi 的正弦值,并将结果打印到控制台。 最后,使用 fmt.Println() 函数将变量和常量的值打印到控制台。 该代码展示了Go语言中变量声明和赋值的各种方式,以及如何使用常量和调用数学函数。

2.2.3 if else:

package main
​
import "fmt"
​
func main() {
    if 7%2 == 0 {
        fmt.Println("7 is even")
    } else {
        fmt.Println("7 if odd")
    }
    if 8%4 == 0 {
        fmt.Println("8 is divisible by 4")
    }
    if num := 9; num < 0 {
        fmt.Println(num, "is negative")
    } else if num < 10 {
        fmt.Println(num, "has 1 digit")
    } else {
        fmt.Println(num, "has nultiple digits")
    }
}
​

这段代码是一个Go语言程序,包含了条件语句的使用。 首先,使用 if 条件语句判断 7 是否为偶数,如果满足条件,则输出 "7 is even",否则输出 "7 if odd"。 接着,再使用 if 条件语句判断 8 是否可以被 4 整除,如果满足条件,则输出 "8 is divisible by 4"。 然后,使用 if 条件语句结合短变量声明的方式,声明一个新的变量 num 并赋值为 9。接着判断 num 的大小,如果它小于 0,则输出 "9 is negative",如果它小于 10,则输出 "9 has 1 digit",否则输出 "9 has multiple digits"。 通过这段代码的示例,展示了Go语言中条件语句的使用方式。条件语句可以根据不同的条件来执行不同的代码块,可以嵌套使用以实现更复杂的逻辑。

2.2.4 循环 :

package main
​
import "fmt"func main() {
    i := 1
    for {
        fmt.Println("loop")
        break
    }
    for j := 7; j < 9; j++ {
        fmt.Println(j)
    }
    for n := 0; n < 5; n++ {
        if n%2 == 0 {
            continue
        }
        fmt.Println(n)
    }
    for i <= 3 {
        fmt.Println(i)
        i = i + 1
    }
}
​

这段代码是一个Go语言程序,展示了不同类型的循环语句的使用方式。 首先,使用无限循环 for {},在循环体中打印 "loop" 并使用 break 语句跳出循环。 接着,使用普通循环 for j := 7; j < 9; j++,循环变量 j 从 7 开始递增,当 j 小于 9 时持续循环,每次循环打印 j 的值。 然后,使用普通循环 for n := 0; n < 5; n++,循环变量 n 从 0 开始递增,当 n 小于 5 时持续循环,每次循环判断 n 是否为偶数,如果是偶数则使用 continue 语句跳过本次循环,否则打印 n 的值。 最后,使用条件循环 for i <= 3,当 i 小于或等于 3 时持续循环,每次循环打印 i 的值,并递增 i 的值。 通过这段代码的示例,展示了Go语言中不同类型的循环语句的使用方式,包括无限循环、普通循环和条件循环,以及 breakcontinue 语句在循环中的使用。

2.2.5 Switch:

package main
​
import (
    "fmt"
    "time"
)
​
func main() {
    a := 2
    switch a {
    case 1:
        fmt.Println(" one")
    case 2:
        fmt.Println("two ")
    case 3:
        fmt.Println("three")
    case 4, 5:
        fmt.Println("four or five")
    default:
        fmt.Println("other")
    }
    t := time.Now()
    switch {
    case t.Hour() < 12:
        fmt.Println("It's before noon")
    default:
        fmt.Println("It's after noon")
    }
}
​

这段代码是一个基本的Go语言程序,主要包含了使用switch语句的几种用法。 首先,定义了一个整型变量a,并将其赋值为2。接下来使用switch语句对变量a进行判断。根据a的值,可以进入不同的case分支,每个case后面跟着一个执行的代码块。这里的case分支分别为1、2、3和4、5,根据a的值为2,所以会进入第二个case,打印输出"two"。 接着,使用time包获取当前时间,并通过switch语句对时间进行判断。在这个switch语句中,没有具体的判断条件,而是使用了空的switch表达式。在每个case语句中,根据具体的条件判断执行的代码块。这里判断如果当前时间的小时数小于12,则打印输出"It's before noon",否则打印输出"It's after noon"。 总体来说,这段代码展示了Go语言中switch语句的几种用法,包括根据变量值进行分支判断和根据条件进行分支判断。通过switch语句,可以根据不同的条件来执行不同的代码块,提高程序的灵活性和可读性。

2.2.6 数组:

package main
​
import "fmt"
​
func main() {
    var a [5]int
    a[4] = 100
    fmt.Println(a[4], len(a))
    b := [5]int{1, 2, 3, 4, 5}
    fmt.Println(b)
    var twoD [2][3]int
    for i := 0; i < 2; i++ {
        for j := 0; j < 3; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)
}
​

这段代码演示了Go语言中数组的基本使用。 首先,定义了一个长度为5的整型数组a。通过索引赋值的方式,将第5个元素设置为100。然后使用索引访问数组元素,打印输出了a[4]的值和数组的长度len(a)。 接下来定义了一个长度为5的整型数组b,并使用字面值初始化数组的各个元素。然后通过打印输出,展示了数组b的内容。 接着,定义了一个二维数组twoD,其大小为2行3列。使用嵌套循环的方式,给每个元素赋值,值为该元素的行索引与列索引之和。最后通过打印输出,展示了整个二维数组的内容。 总体来说,这段代码展示了如何定义和操作数组,包括数组的初始化、元素赋值和访问等操作。通过数组的使用,可以有效地存储和管理一组相关的数据。

2.2.7 切片:

package main
​
import "fmt"func main() {
    s := make([]string, 3)
    s[0] = "a"
    s[1] = "b"
    s[2] = "c"
    fmt.Println("get: ", s[2])   // c
    fmt.Println("len: ", len(s)) // 3
​
    s = append(s, "d")
    s = append(s, "e", "f")
    fmt.Println(s) // [a b c d e f]
    c := make([]string, len(s))
    copy(c, s)
    fmt.Println(c)      // [a b c d e f]
    fmt.Println(s[2:5]) // [c d e]
    fmt.Println(s[:5])  // [a b c d e]
    fmt.Println(s[2:])  // [c d e f]
​
    good := []string{"g", "o", "o", "d"}
    fmt.Println(good) // [g o o d]
}

这段代码展示了对于切片的操作。首先,使用 make 函数创建了一个长度为 3 的切片 s,并分别给切片的元素赋值。然后使用 fmt.Println 打印了切片 s 的第 2 个元素以及切片的长度。接着,使用 append 函数向切片 s 末尾添加了元素 "d",然后继续添加了元素 "e" 和 "f"。再次使用 fmt.Println 打印切片 s,可以看到新添加的元素被成功追加到切片末尾。接下来,使用 make 函数创建了一个长度与切片 s 相同的切片 c,然后使用 copy 函数将切片 s 的内容复制到切片 c 中。再次使用 fmt.Println 打印切片 c,可以看到切片 s 的内容成功复制到了切片 c。继续使用切片表达式 s[2:5],可以获取切片 s 中索引从 2 到 4 的子切片,而不包含索引 5。使用 fmt.Println 打印该子切片,可以看到输出为 [c d e]。最后,使用 fmt.Println 打印了切片 s 的三种不同的切片表达式: s[:5] 表示从切片开头到索引 4 的子切片,输出为 [a b c d e];s[2:] 表示从索引 2 到切片末尾的子切片,输出为 [c d e f]。而变量 good 是通过字面量直接创建的切片,其内容为 ["g" "o" "o" "d"]。最后使用 fmt.Println 打印了切片 good

2.2.8 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(r, ok) // 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)
}
​

这代码展示了对于映射(map)的操作。首先,使用 make 函数创建了一个空的映射 m。然后,使用 [key] = value 的方式给映射 m 添加了两个键值对。通过 fmt.Println 可以打印出映射 m 的内容,得到输出 map[one:1 two:2],表示映射 m 中的键值对。使用 len 函数获取映射 m 的长度,得到输出 2,表示映射中键值对的个数。 接下来,通过 m["one"] 的方式获取映射中键 "one" 对应的值,得到输出 1。再次通过 m["unknown"] 的方式获取映射中不存在的键 "unknown" 对应的值,得到输出 0。这是因为这个键在映射中不存在,所以返回了该类型的零值。 继续使用 r, ok := m["unknown"] 的方式获取映射中键 "unknown" 对应的值和是否存在的布尔值。得到输出 0 false,其中 r 表示映射中 "unknown" 对应的值,ok 表示键是否存在。 然后使用 delete 函数从映射中删除了键 "one" 对应的键值对。再次使用 fmt.Println 打印映射 m 的内容,得到输出 map[two:2],表示键 "one" 对应的键值对已被删除。 接下来,使用字面量的方式创建了两个映射 m2m3,分别通过指定键值对和类型推断的方式完成初始化。最后使用 fmt.Println 打印出映射 m2m3 的内容,得到输出 map[one:1 two:2] map[one:1 two:2],表示两个映射分别含有相同的键值对。

2.2.9 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) // index: 0 num: 2
		}
	}
	fmt.Println(sum) // 9
	m := map[string]string{"a": "A", "b": "B"}
	for k, v := range m {
		fmt.Println(k, v) // b 8; a A
	}
	for k := range m {
		fmt.Println("key", k) // key a; key b
	}
}

这段代码是一个Go语言程序,它的主要功能是对一个整数切片和一个字符串映射进行迭代操作,并输出相应的结果。

首先,代码导入了"fmt"包,用于实现输入和输出功能。

在main函数中,定义了一个整数切片nums,其包含了三个元素{2, 3, 4},以及一个整数变量sum并初始化为0。

接下来,使用for循环和range关键字迭代nums切片。在每次迭代中,将当前元素赋值给num,并将其与2进行比较。如果相等,则使用fmt包的Println函数输出当前迭代的索引i和元素值num。

在第一个for循环结束后,使用fmt包的Println函数输出sum的值,即9。

接下来,定义了一个字符串映射m,其中键值对为{"a": "A", "b": "B"}。

再次使用for循环和range关键字迭代映射m。在每次迭代中,将当前键赋值给变量k,将当前值赋值给变量v,并使用fmt包的Println函数输出键值对k和v。

在第二个for循环结束后,使用for循环和range关键字迭代映射m的键。在每次迭代中,将当前键赋值给变量k,并使用fmt包的Println函数输出键k。

最终,程序输出的结果为: index: 0 num: 2 9 b B a A key a key b

2.2.10 function:

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
}

这段代码是一个Go语言程序,它定义了一些函数并在主函数中进行调用,并输出相应的结果。

首先,代码导入了"fmt"包,用于实现输入和输出功能。

接下来,定义了一个名为add的函数,该函数接收两个整数参数a和b,并返回它们的和。函数体中使用return语句返回a和b的和。

然后,定义了一个名为add2的函数,该函数也接收两个整数参数a和b,并返回它们的和。与add函数不同的是,add2函数省略了参数类型,因为它们都是同一类型。函数体中使用return语句返回a和b的和。

接着,定义了一个名为exists的函数,该函数接收一个字符串映射m和一个字符串键k作为参数,并返回对应键的值和一个布尔值表示是否存在该键。函数体中,使用m[k]获取键k对应的值,并将其赋值给变量v和ok。最后,使用return语句返回v和ok。

在主函数main中,调用了add函数,并将返回值赋给变量res。然后,使用fmt包的Println函数输出res的值,即3。

接下来,使用exists函数检查一个字符串映射中是否存在键"a"。将返回的值和布尔结果分别赋给变量v和ok。最后,使用fmt包的Println函数输出v和ok的值,即"A"和true。

最终,程序输出的结果为: 3 A true

2.2.11 pointer:

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
}

这段代码是一个Go语言程序,它定义了两个函数add2和add2ptr,并在主函数中进行调用,并输出相应的结果。

首先,代码导入了"fmt"包,用于实现输入和输出功能。

接下来,定义了一个名为add2的函数,该函数接收一个整数参数n,并对其进行加2的操作。函数体中,将n加2后的结果不返回,而是直接修改了传入的参数n的值。

然后,定义了一个名为add2ptr的函数,该函数接收一个整数指针参数n,并对指针指向的值进行加2的操作。函数体中,通过解引用指针,将指针指向的值加2后的结果赋值给指针指向的值。

在主函数main中,首先定义了一个整数变量n并初始化为5。

然后,调用了add2函数,并将n作为参数传入。由于add2函数中对参数n的修改不会影响到外部的变量n,所以在调用完add2函数后,使用fmt包的Println函数输出n的值,即5。

接下来,调用了add2ptr函数,并将n的地址作为参数传入。由于add2ptr函数中对指针指向的值进行了修改,所以在调用完add2ptr函数后,使用fmt包的Println函数输出n的值,即7。

最终,程序输出的结果为: 5 7

2.2.12 Structure:

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
}

这段代码是一个Go语言程序,它定义了一个名为user的结构体类型,并在主函数中创建了几个user类型的变量,并调用了两个函数进行密码验证,并输出相应的结果。

首先,代码导入了"fmt"包,用于实现输入和输出功能。

接下来,定义了一个名为user的结构体类型,该结构体包含两个字段:name和password,分别表示用户名和密码。

在主函数main中,首先创建了一个名为a的user类型的变量,并使用键值对的方式为字段赋值,即name为"wang",password为"1024"。

然后,创建了一个名为b的user类型的变量,并直接使用字段值的方式为字段赋值,即name为"wang",password为"1024"。

接着,创建了一个名为c的user类型的变量,并使用键值对的方式为name字段赋值,即name为"wang",然后通过点操作符为password字段赋值,即password为"1024"。

接下来,创建了一个名为d的user类型的变量,并通过点操作符为name和password字段分别赋值,即name为"wang",password为"1024"。

然后,使用fmt包的Println函数输出变量a、b、c和d的值,即{wang 1024}、{wang 1024}、{wang 1024}、{wang 1024}。

接下来,调用了名为checkPassword的函数,并将变量a和字符串"haha"作为参数传入。该函数会判断参数u的password字段是否等于参数password,并返回相应的结果。由于a的password字段为"1024",与"haha"不相等,所以输出结果为false。

然后,调用了名为checkPassword2的函数,并将变量a的地址和字符串"haha"作为参数传入。该函数接收一个指向user类型的指针参数u,并判断指针指向的user的password字段是否等于参数password,并返回相应的结果。由于a的password字段为"1024",与"haha"不相等,所以输出结果为false。

最终,程序输出的结果为: {wang 1024} {wang 1024} {wang 1024} {wang 1024} false false

2.2.13 Struct method:

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")) // true
}

这段代码是一个Go语言程序,它定义了一个名为user的结构体类型,并为该类型定义了两个方法:checkPassword和resetPassword。在主函数中,创建了一个user类型的变量a,并调用了resetPassword方法来重置密码,然后使用checkPassword方法来验证密码,并输出相应的结果。

首先,代码导入了"fmt"包,用于实现输入和输出功能。

接下来,定义了一个名为user的结构体类型,该结构体包含两个字段:name和password,分别表示用户名和密码。

然后,定义了一个名为checkPassword的方法,该方法的接收者是user类型的值u,它比较u的password字段与参数password是否相等,并返回相应的结果。

接着,定义了一个名为resetPassword的方法,该方法的接收者是user类型的指针u,它将u的password字段重置为参数password。

在主函数main中,首先创建了一个名为a的user类型的变量,并使用键值对的方式为字段赋值,即name为"wang",password为"1024"。

然后,调用了a的resetPassword方法,并将字符串"2048"作为参数传入。该方法会将a的password字段重置为"2048"。

接下来,调用了a的checkPassword方法,并将字符串"2048"作为参数传入。该方法会判断a的password字段是否等于参数password,并返回相应的结果。由于a的password字段为"2048",与参数"2048"相等,所以输出结果为true。

最终,程序输出的结果为: true

2.2.14 Error handling:

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([]user{{"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)
	}
}

这段代码是一个Go语言程序,它定义了一个名为user的结构体类型,并定义了一个名为findUser的函数来查找用户。在主函数中,使用findUser函数来查找用户,并根据结果输出相应的信息。

首先,代码导入了"fmt"和"errors"包,用于实现输入和输出功能以及错误处理。

接下来,定义了一个名为user的结构体类型,该结构体包含两个字段:name和password,分别表示用户名和密码。

然后,定义了一个名为findUser的函数,该函数接收一个user类型的切片users和一个字符串name作为参数,它会遍历users切片,查找name匹配的用户,并返回指向该用户的指针和一个错误(如果找不到用户,则返回nil和一个错误)。

在主函数main中,首先调用了findUser函数,并传入一个包含一个用户的切片和字符串"wang"作为参数。该函数会查找切片中name为"wang"的用户,并返回指向该用户的指针和nil的错误。

接下来,使用:=语法对返回的结果进行解构赋值,将指针赋值给变量u,将错误赋值给变量err。

然后,使用fmt包的Println函数输出变量u的name字段的值,即"wang"。

接着,使用:=语法再次调用了findUser函数,并传入一个包含一个用户的切片和字符串"li"作为参数。由于找不到name为"li"的用户,所以该函数会返回nil的指针和一个错误。

然后,使用:=语法对返回的结果进行解构赋值,将nil的指针赋值给变量u,将错误赋值给变量err。

接下来,使用fmt包的Println函数输出变量err的值,即"not found"。

最终,程序输出的结果为: wang not found

2.2.15 String operations:

package main

import (
	"fmt"
	"strings"
)

func main() {
	a := "hello"
	fmt.Println(strings.Contains(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-llofmt .Println( strings.Repeat( a,2 ))	// hellohel
	fmt.Println(strings.Replace(a, "e", "E", -1))         // 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
}

这段代码是一个Go语言程序,它使用了"strings"包来操作字符串,并输出相应的结果。

首先,代码导入了"fmt"和"strings"包,用于实现输入和输出功能以及字符串操作。

在主函数main中,首先定义了一个字符串变量a,并赋值为"hello"。

然后,使用fmt包的Println函数调用了strings包的Contains函数,判断字符串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函数,查找子串"ll"在字符串a中第一次出现的位置,并输出结果为2。

接下来,使用fmt包的Println函数调用了strings包的Join函数,将切片[]string{"he", "llo"}中的元素使用"-"连接起来,并输出结果为"he-llo"。

然后,使用fmt包的Println函数调用了strings包的Repeat函数,将字符串a重复两次,并输出结果为"hellohello"。

接着,使用fmt包的Println函数调用了strings包的Replace函数,将字符串a中的子串"e"替换为"E",并输出结果为"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。

最终,程序输出的结果为: true 2 true true 2 he-llo hellohello hEllo [a b c] hello HELLO 5 6

2.2.16 String formatting:

package main

import "fmt"

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=%vin", n)   // n=123
	fmt.Printf(" p=%vin", 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 : l, y:2}
	f := 3.141592653
	fmt.Println(f)          // 3.141592653
	fmt.Printf("%.2f\n", f) // 3.14
}

这段代码是一个Go语言程序,它使用了"fmt"包来进行格式化输出。

首先,定义了一个结构体类型point,包含两个整型字段x和y。

在主函数main中,首先定义了三个变量s、n和p,分别赋值为字符串"hello"、整数123和point结构体类型的值{1, 2}。

然后,使用fmt包的Println函数,分别输出变量s和n的值,结果为"hello 123"。

接着,使用fmt包的Println函数,输出结构体变量p的值,结果为"{1 2}"。

然后,使用fmt包的Printf函数,使用格式化字符串%s,输出变量s的值,结果为"s=hello"。

接下来,使用fmt包的Printf函数,使用格式化字符串%v,输出变量n的值,结果为"n=123"。

然后,使用fmt包的Printf函数,使用格式化字符串%v,输出结构体变量p的值,结果为"p={1 2}"。

接着,使用fmt包的Printf函数,使用格式化字符串%+v,输出结构体变量p的值,结果为"p={x:1 y:2}"。

然后,使用fmt包的Printf函数,使用格式化字符串%#v,输出结构体变量p的值,结果为"p=main.point{x:1, y:2}"。

接下来,定义了一个浮点数变量f,并赋值为3.141592653。

最后,使用fmt包的Println函数,输出变量f的值,结果为"3.141592653"。

接着,使用fmt包的Printf函数,使用格式化字符串%.2f,输出变量f的值,结果为"3.14",保留两位小数。

最终,程序输出的结果为: hello 123 {1 2} s=hello n=123 p={1 2} p={x:1 y:2} p=main.point{x:1, y:2} 3.141592653 3.14

2.2.17 JSON processing:

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)) //i"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")
}

这段代码是一个Go语言程序,它使用了"encoding/json"包来进行JSON数据的编码和解码。

首先,定义了一个结构体类型userInfo,包含三个字段Name、Age和Hobby。

在主函数main中,首先定义了一个变量a,赋值为一个userInfo结构体类型的值,其中Name为"wang",Age为18,Hobby为一个包含两个字符串元素的切片。

然后,使用json包的Marshal函数将变量a编码为JSON格式的字节流,并将结果赋值给变量buf。

接着,使用fmt包的Println函数输出变量buf的值,结果为一个字节数组的表示形式。

然后,使用fmt包的Println函数输出变量buf的字符串表示形式,结果为一个JSON字符串。

接下来,使用json包的MarshalIndent函数将变量a编码为JSON格式的字节流,并将结果赋值给变量buf。

然后,使用fmt包的Println函数输出变量buf的字符串表示形式,结果为一个格式化的JSON字符串,使用制表符进行缩进。

接着,定义了一个变量b,类型为userInfo。

然后,使用json包的Unmarshal函数将变量buf解码为JSON格式,并将结果赋值给变量b。

接下来,使用fmt包的Printf函数,使用格式化字符串%#v,输出变量b的值,结果为解码后的userInfo结构体类型的值,包含Name、Age和Hobby字段的值。

最终,程序输出的结果为: [123 34 78 97 109 101 34 58 34 119 97 110 103 34 44 34 65 103 101 34 58 49 56 44 34 72 111 98 98 121 34 58 91 34 71 111 108 97 110 103 34 44 34 84 121 112 101 83 99 114 105 112 116 34 93 125] {"Name":"wang","Age":18,"Hobby":["Golang","TypeScript"]} { "Name": "wang", "Age": 18, "Hobby": [ "Golang", "TypeScript" ] } main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}

2.2.18 Time processing:

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now) //2022-0soe 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 01: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"))
	diff := t2.Sub(t)
	fmt.Println(diff)
	fmt.Println(diff.Minutes(), diff.Seconds()) //63 3900
	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)    // true
	fmt.Println(now.Unix()) //1648738080
}

这段代码是一个Go语言程序,它使用了"time"包来处理日期和时间。

在主函数main中,首先使用time包的Now函数获取当前时间,并将结果赋值给变量now。

然后,使用fmt包的Println函数输出变量now的值,结果为当前时间的字符串表示形式。

接下来,使用time包的Date函数创建一个时间对象t,表示2022年3月27日1时25分36秒,时区为UTC。

然后,使用time包的Date函数创建另一个时间对象t2,表示2022年3月27日2时30分36秒,时区为UTC。

接着,使用fmt包的Println函数输出变量t的值,结果为t的字符串表示形式。

然后,使用fmt包的Println函数输出变量t的年、月、日、小时和分钟的值。

接下来,使用fmt包的Println函数和time包的Format方法,将变量t的值按照指定的格式化字符串进行格式化输出,结果为"2022-03-27 01:25:36"。

接着,使用time包的Sub方法计算t2和t之间的时间差,并将结果赋值给变量diff。

然后,使用fmt包的Println函数输出变量diff的值,结果为时间差的字符串表示形式。

接下来,使用fmt包的Println函数输出变量diff的分钟数和秒数的值。

然后,使用time包的Parse方法将字符串"2022-03-27 01:25:36"解析为时间对象,并将结果赋值给变量t3。

接着,使用fmt包的Println函数输出t3和t是否相等的结果,结果为true。

最后,使用fmt包的Println函数输出当前时间的Unix时间戳,结果为当前时间的秒数。

最终,程序输出的结果为: 2022-03-27 01:25:36.123456789 2022-03-27 01:25:36 +0000 UTC 2022 March 27 1 25 2022-03-27 01:25:36 1h5m0s 65 3900 true 1648738080

2.2.19 Number parsing:

package main

import (
	"fmt"
	"strconv"
)

func main() {
	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.Ato i : parsing "AAA" : invalid syntax
}

这段代码是一个Go语言程序,它使用了"strconv"包来进行字符串和基本数据类型之间的转换。

在主函数main中,首先使用strconv包的ParseFloat函数将字符串"1.234"转换为浮点数,并将结果赋值给变量f。

然后,使用fmt包的Println函数输出变量f的值,结果为1.234。

接下来,使用strconv包的ParseInt函数将字符串"111"转换为十进制的整数,并将结果赋值给变量n。

然后,使用fmt包的Println函数输出变量n的值,结果为111。

接着,使用strconv包的ParseInt函数将字符串"0x1000"转换为十六进制的整数,并将结果赋值给变量n。

然后,使用fmt包的Println函数输出变量n的值,结果为4096。

接下来,使用strconv包的Atoi函数将字符串"123"转换为整数,并将结果赋值给变量n2。

然后,使用fmt包的Println函数输出变量n2的值,结果为123。

接着,使用strconv包的Atoi函数将字符串"AAA"转换为整数,并将结果赋值给变量n2。

然后,使用fmt包的Println函数输出变量n2和错误err的值,结果为0和一个错误信息,表示转换失败。

最终,程序输出的结果为: 1.234 111 4096 123 0 strconv.Atoi: parsing "AAA": invalid syntax

2.2.20 Process information:

package main

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

func main() {
	//go run example/ 20-env/main.go a b c d
	fmt.Println(os.Args)           // [/var/folders/8p/n34xxfnx38dg8bv_x8162t_m0000gn/T/go-build34069812767b001/exe/main a b c d ]
	fmt.Println(os.Getenv("PATH")) //usr/local/go/bin. . .
	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)) // 127.0.0.1	localhost
}

这段代码是一个Go语言程序,它使用了"os"和"os/exec"包来进行操作系统相关的功能。

在主函数main中,首先使用fmt包的Println函数输出os.Args的值,结果为一个字符串切片,包含了程序运行时的命令行参数。

然后,使用fmt包的Println函数输出os.Getenv("PATH")的值,结果为环境变量PATH的值。

接着,使用os.Setenv函数将环境变量AA的值设置为BB,并使用fmt包的Println函数输出设置后的环境变量AA的值。

然后,使用exec包的Command函数创建一个命令,该命令是在终端中执行grep命令来搜索文件/etc/hosts中包含"127.0.0.1"的行。

接着,使用CombinedOutput方法执行命令,并将命令的输出结果保存在变量buf中。

然后,使用fmt包的Println函数输出buf的值,结果为命令的输出结果。

最后,如果执行命令过程中出现错误,则使用panic函数抛出异常。

最终,程序输出的结果为: [/var/folders/8p/n34xxfnx38dg8bv_x8162t_m0000gn/T/go-build34069812767b001/exe/main a b c d] usr/local/go/bin. . . 127.0.0.1 localhost

03复习

Go语言是一种静态类型、编译型的开源编程语言,具有简洁、高效、并发等特点。以下是Go语言的基础语法知识的简要介绍。

  1. 变量和赋值: Go语言使用var关键字声明变量,可以显式指定类型,也可以由编译器根据赋值自动推断。例如:var a int、var b, c string = "hello", "world"、d := 10。
  2. 基本数据类型: Go语言提供了整型、浮点型、布尔型和字符串类型等基本数据类型。例如:var num int = 10、var pi float64 = 3.14、var isTrue bool = true、var str string = "hello"。
  3. 数组和切片: 数组是一组相同类型的数据的集合,长度固定;切片是对数组的抽象,长度可变。例如:var arr [5]int、arr[0] = 1、slice := []int{1, 2, 3}。
  4. 映射: 映射是一种无序的键值对集合。例如:var m map[string]int、m = make(map[string]int)、m["apple"] = 1。
  5. 条件语句: Go语言使用if语句和switch语句进行条件判断。例如:if x > 10 { fmt.Println("x is greater than 10") } else { fmt.Println("x is less than or equal to 10") }、switch day { case "Monday": fmt.Println("Today is Monday") case "Tuesday": fmt.Println("Today is Tuesday") default: fmt.Println("Today is another day") }。
  6. 循环语句: Go语言使用for语句进行循环。例如:for i := 0; i < 5; i++ { fmt.Println(i) }、names := []string{"Alice", "Bob", "Charlie"} for index, name := range names { fmt.Println(index, name) }。
  7. 函数: 函数是Go语言的基本组成单元,可以接收参数并返回结果。例如:func add(a, b int) int { return a + b }、result := add(1, 2)。
  8. 结构体: 结构体是一种自定义的数据类型,可以包含多个字段。例如:type Person struct { name string age int }、p := Person{name: "Alice", age: 20}、fmt.Println(p.name, p.age)。
  9. 并发编程: Go语言内置了轻量级的并发机制,可以通过goroutine和channel来实现并发编程。例如:func worker(id int, jobs <-chan int, results chan<- int) { ... }、jobs := make(chan int, 100)、results := make(chan int, 100)、go worker(w, jobs, results)、jobs <- j、<-results。

以上是Go语言的基础语法知识的简要介绍,希望对您有所帮助。要深入学习和使用Go语言,建议阅读官方文档和参考书籍,进行实际的编程练习。