方向三-Go 语言入门指南:基础语法和常用特性解析 | 豆包MarsCode AI刷题

56 阅读11分钟
01-hello
package main

import (
	"fmt"
)

func main() {
	fmt.Println("hello world")
}
  1. package main:这一行声明了这个文件属于main包。在Go语言中,每个程序必须属于一个包,而main包是一个特殊的包,它定义了一个可执行程序的入口点。
  2. import "fmt":这一行导入了fmt包,fmt包是Go语言标准库中的一个包,它提供了格式化输入和输出的函数,例如Println函数。
  3. func main() {...}:这是main函数的定义,main函数是程序的入口点,当你运行这个程序时,程序会从这里开始执行。
  4. fmt.Println("hello world"):这一行调用了fmt包中的Println函数,它的作用是打印出"hello world"。Println函数会自动在字符串的末尾添加一个换行符。
02-var
package main

import (
	"fmt"
	"math"
)

func main() {

	var a = "initial"

	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) // initial 1 2 true 0 0
	fmt.Println(g)                // initialapple

	const s string = "constant"
	const h = 500000000
	const i = 3e20 / h
	fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}

这段代码是用Go语言编写的一个简单程序,它展示了变量的声明、赋值和使用,以及常量的定义和使用。同时,它还使用了标准库中的fmt包来进行格式化输出,以及math包来进行数学运算。

下面是对代码的详细解释:

  1. package main:声明这是一个名为main的包,每个Go程序都必须包含一个main包,它定义了程序的入口点。

  2. import ("fmt"; "math"):导入了两个标准库包,fmt包用于格式化输入和输出,math包提供了数学函数和常量。

  3. func main() {...}:定义了程序的入口函数main,程序从这里开始执行。

  4. 变量声明和赋值:

    • var a = "initial":声明一个字符串变量a并赋值为"initial"。
    • var b, c int = 1, 2:同时声明两个整数变量bc,并分别赋值为1和2。
    • var d = true:声明一个布尔变量d并赋值为true
    • var e float64:声明一个浮点变量e,但没有立即赋值。
    • f := float32(e):使用短变量声明符号:=声明一个新的变量f,并将e转换为float32类型后赋值给f
    • g := a + "foo":使用短变量声明符号:=声明一个新的变量g,并将a和"foo"拼接后赋值给g
  5. 使用fmt.Println打印变量的值:

    • fmt.Println(a, b, c, d, e, f):打印变量abcdef的值。
    • fmt.Println(g):打印变量g的值。
  6. 常量的定义和使用:

    • const s string = "constant":定义一个字符串常量s并赋值为"constant"。
    • const h = 500000000:定义一个整数常量h并赋值为500000000。
    • const i = 3e20 / h:定义一个浮点常量i,其值为3e20除以h
  7. 使用fmt.Println打印常量的值和数学函数的结果:

    • fmt.Println(s, h, i, math.Sin(h), math.Sin(i)):打印常量shi的值,以及math.Sin(h)math.Sin(i)的结果
03-for
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 ++
	}
}

go语言的for循环和c语言的差不多

04-if
package main

import "fmt"

func main() {

	if 7%2 == 0 {
		fmt.Println("7 is even")
	} else {
		fmt.Println("7 is 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 multiple digits")
	}
}

if判断语句跟c语言相比少了括号,但判断及分支没变

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

跟c++相比少了括号

06-array
package main

import "fmt"

func main() {

	var a [5]int
	a[4] = 100
	fmt.Println("get:", a[2])
	fmt.Println("len:", 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)
}

数组array大体跟Java、c++差不多

07-slice
package main

import "fmt"

func main() {

    // 创建一个长度为3的字符串切片
    s := make([]string, 3)
    s[0] = "a"
    s[1] = "b"
    s[2] = "c"
    
    // 输出切片的第三个元素(索引从0开始)
    fmt.Println("get:", s[2])   // 输出: get: c
    
    // 输出切片的长度
    fmt.Println("len:", len(s)) // 输出: len: 3

    // 使用 append 函数扩展切片,添加一个元素 "d"
    s = append(s, "d")
    
    // 再次使用 append 函数扩展切片,添加两个元素 "e" 和 "f"
    s = append(s, "e", "f")
    
    // 输出扩展后的切片
    fmt.Println(s) // 输出: [a b c d e f]

    // 创建一个新的切片 c,长度与 s 相同
    c := make([]string, len(s))
    
    // 将 s 中的内容复制到 c
    copy(c, s)
    
    // 输出复制后的切片 c
    fmt.Println(c) // 输出: [a b c d e f]

    // 输出切片 s 的第 2 到第 4 个元素(索引 2 到 4)
    fmt.Println(s[2:5]) // 输出: [c d e]
    
    // 输出切片 s 的前 5 个元素(索引 0 到 4)
    fmt.Println(s[:5])  // 输出: [a b c d e]
    
    // 输出切片 s 的第 2 个元素到最后一个元素(索引 2 到末尾)
    fmt.Println(s[2:])  // 输出: [c d e f]

    // 创建一个包含 "g", "o", "o", "d" 的切片
    good := []string{"g", "o", "o", "d"}
    
    // 输出切片 good
    fmt.Println(good) // 输出: [g o o d]
}

以上代码展示了如何在 Go 语言中创建、修改、扩展和复制切片,以及如何使用切片的切片slice操作。

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

以上代码展示了Go语言如何操作映射map,包括创建、修改、查询、删除和初始化映射。

09-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", "c":"C"}
	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 语言中使用range 关键字遍历切片和映射。通过这些操作,可以灵活地处理集合中的数据。

10-func
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语言如何定义和调用函数,包括简单的加法函数和一个检查映射中键是否存在并返回值的函数。

11-point
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语言的指针跟c++语言的指针一样

12-struct
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, "1024"))   // false
	fmt.Println(checkPassword2(&a, "1024")) // false
}

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

func checkPassword2(u *user, password string) bool {
	return u.password == password
}

Go语言的结构体函数跟c++语言的结构体差不多

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 语言中定义结构体和方法,并使用这些方法来操作结构体的字段。通过值接收者和指针接收者的不同使用,可以灵活地实现不同的功能。值接收者适用于不需要修改结构体字段的方法,而指针接收者适用于需要修改结构体字段的方法。

14-error
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 语言中定义结构体和方法,并在一个用户列表中查找特定的用户。通过使用指针返回找到的用户,可以避免不必要的拷贝。同时,通过返回错误信息,可以处理未找到用户的情况。这种设计使得代码更加健壮和易于维护。

15-string
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-llo
	fmt.Println(strings.Repeat(a, 2))                     // hellohello
	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 包中的各种字符串处理函数。通过这些函数,可以方便地进行字符串的查找、计数、分割、连接、替换、大小写转换等操作。同时,len 函数可以用来计算字符串的字节长度,这对于处理多字节字符(如中文字符)尤为重要。跟Java和C++的string封装类差不多。

16-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) // hello 123
	fmt.Println(p)    // {1 2}

	fmt.Printf("s=%v\n", s)  // s=hello
	fmt.Printf("n=%v\n", n)  // n=123
	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)          // 3.141592653
	fmt.Printf("%.2f\n", f) // 3.14
}

上述代码展示了如何在 Go 语言中使用 fmt 包中的各种格式化函数来打印不同类型的数据。通过这些函数,可以方便地进行字符串、整数、浮点数和结构体的格式化输出。特别是 fmt.Printf 函数提供了丰富的格式化选项,可以满足多种输出需求。

17-json
package main

import (
	"encoding/json"
	"fmt"
)

type userInfo struct {
	Name  string
	Age   int 
	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)         // [123 34 78 97...]
	fmt.Println(string(buf)) // {"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.Marshaljson.Unmarshal 函数,可以方便地将结构体转换为 JSON 字符串,或将 JSON 字符串转换回结构体。json.MarshalIndent 函数提供了带缩进的 JSON 输出,使输出更易读。

18-time
package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now) // 2022-03-27 18:04:59.433297 +0800 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"))                    // 2022-03-27 01:25:36
	diff := t2.Sub(t)
	fmt.Println(diff)                           // 1h5m0s
	fmt.Println(diff.Minutes(), diff.Seconds()) // 65 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 包来处理日期和时间。通过 time.Nowtime.Datetime.Parse 等函数,可以方便地获取、创建、解析和格式化时间。time.Duration 类型用于表示时间间隔,可以进行时间差值的计算。Unix 方法用于获取时间的 Unix 时间戳,适用于需要时间戳的场景。

19-strconv
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.Atoi: parsing "AAA": invalid syntax
}

上述代码展示了如何在 Go 语言中使用 strconv 包中的函数将字符串转换为不同的数值类型。strconv.ParseFloat 用于将字符串转换为浮点数,strconv.ParseInt 用于将字符串转换为整数,并且可以指定基数,strconv.Atoi 用于将字符串转换为 int 类型。通过这些函数,可以方便地进行字符串和数值之间的转换,并处理可能的错误。

20-env
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_x8l62t_m0000gn/T/go-build3406981276/b001/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 语言中使用 osos/exec 包来处理命令行参数、环境变量和外部命令的执行。通过 os.Args 可以获取命令行参数,os.Getenvos.Setenv 可以获取和设置环境变量,exec.CommandCombinedOutput 可以执行外部命令并捕获其输出。这些功能在编写需要与操作系统交互的程序时非常有用。