Go 语言入门指南:基础语法和常用特性解析

111 阅读16分钟

掘金社区笔记


字节跳动为什么会全面拥抱GO语言

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

开发环境配置

开发环境

下载开发环境地址—-安装

go.dev/

studygolang.com/dl

goproxy.cn/

基于云开发的开发环境

gitpod.io/#github.com…

短链接:

hi-hi.cn/gitpod

基础语法-变量

package main
import{
    "fmt"
    "math"
}

func main(){
    var a = "start"
    var b, c int = 1, 2
    var d = true
    var e float64
    f != float32(e)
    g  != a + "go"
    fmt.Println(a, b ,c, d, e, f)
    fmt.Println(g)
    // 定义常量
    const s string = "constant"
    const h = 3450000
    const t = 3e20/ h
    fmt.Println(s, h, math.Sin(h), math.Sin(t))
}

基础语法之If—else

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

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 = i + 1
    }
}

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

数组

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

切片

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]
}
// 输出结果
get: c
len: 3
[a b c d e f]
[a b c d e f]
[c d e]
[a b c d e]
[c d e f]
[g o o d]

集合

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[one:1 two:2]
2
1
0
0 false
map[one:1 two:2] map[one:1 two:2]

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
    }
}
// 输出结果
map[one:1 two:2]
2
1
0
0 false
map[one:1 two:2] map[one:1 two:2]

函数

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
}
// 输出结果
3
A true

指针

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
}
// 输出结果
5
7

结构体(带类型的集合)

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
}
// 输出结果
{wang 1024} {wang 1024} {wang 1024} {wang 1024}
false
false

结构体方法

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
}
// 输出结果
true

错误处理即异常

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)
    }
}
// 输出结果
wang
not found

字符串类型处理操作

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
}
// 输出结果
true
2
true
true
2
he-llo
hellohello
hEllo
[a b c]
hello
HELLO
5
6

字符串格式化

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
}
// 输出结果
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

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

// 输出结果
[123 34 78 97 109 101 34 58 34 119 97 110 103 34 44 34 97 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"}}

时间处理

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
}
// 输出结果
2024-11-14 08:11:45.344380983 +0000 UTC m=+0.000029184
2022-03-27 01:25:36 +0000 UTC
2022 March 27 1 25
2022-03-27 01:25:36
1h5m0s
65 3900
true
1731571905

数字解析

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
}
// 输出结果
1.234
111
4096
123
0 strconv.Atoi: parsing "AAA": invalid syntax

进程信息

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
}
// 输出结果
[/tmp/go-build2648710338/b001/exe/main]
/home/cloudide/.cargo/bin:/home/cloudide/.pyenv/shims:/cloudide/workspace/.tmp/fnm_multishells/394_1731571682041/bin:/home/cloudide/.moon/bin:/home/cloudide/.npm/bin:/cloudide-image/component/builtin/__alias__/cloudide.zijieapi.com/component/core/icube_multi_container@v2.371/release-standalone/bin/remote-cli:/home/cloudide/.local/bin:/home/cloudide/.cargo/bin:/home/cloudide/.local/share/pnpm:/home/cloudide/.local/state/fnm_multishells/157_1731571676810/bin:/home/cloudide/.moon/bin:/home/cloudide/.npm/bin:/home/cloudide/.nix-profile/bin:/home/cloudide/.local/state/nix/builtin/bin:/home/cloudide/.local/bin:/cloudide/component/current/cloudide-staging.zijieapi.com/component/core/icube_user/release-standalone/bin/remote-cli:/cloudide/component/current/cloudide.zijieapi.com/component/core/icube_user/release-standalone/bin/remote-cli:/cloudide/component/current/cloudide-staging.zijieapi.com/component/core/icube/release-standalone/bin/remote-cli:/cloudide/component/current/cloudide.zijieapi.com/component/core/icube/release-standalone/bin/remote-cli:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:node_modules/.bin:node_modules/.bin:/cloudide-image/component/builtin/__alias__/cloudide.zijieapi.com/component/core/icube_multi_container@v2.371/release-standalone
<nil>
127.0.0.1       localhost

Go语言入门案例

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    maxNum := 100
    secretNumber := rand.Intn(maxNum)
    fmt.Println("The secret number is ", secretNumber)
}
//运行结果
The secret number is  19

第一篇笔记:

GO 语言入门指南:基础语法和常用特性解析

一、引言

Go 语言作为一种现代化的编程语言,在当今的软件开发领域中占据着重要地位。它拥有简洁的语法、高效的性能以及丰富的标准库,无论是用于开发网络服务、系统工具还是数据处理应用,都表现出色。在本文中,我们将深入解析 Go 语言的基础语法和常用特性,通过丰富的代码案例,帮助读者更好地理解和掌握这门语言。

二、字节跳动与 Go 语言

字节跳动全面拥抱 Go 语言是有诸多原因的。最初使用 Python,但由于性能问题而更换。C++ 不太适合在线 Web 业务,而早期团队非 JAVA 背景。Go 语言本身性能比较好,部署简单且学习成本低,同时内部RPCHTTP框架的推广也促进了其在字节跳动的广泛应用。这些背景信息让我们看到 Go 语言在大型项目中的优势和适用性。

三、开发环境配置

(一)开发环境下载地址

  1. 官方地址go.dev/ ,这是获取 Go 语言开发环境的官方途径。
  2. 学习网站地址studygolang.com/dl ,为学习 Go 语言的开发者提供方便的下载链接。
  3. 代理地址goproxy.cn/ ,可用于解决网络相关的问题,尤其是在下载依赖包等情况下。

(二)基于云开发的环境

  1. GitHub 相关环境gitpod.io/#github.com… - by - example ,为开发者提供了一个便捷的云开发环境,还有短链接 https://hi - hi.cn/gitpod ,方便快速访问。

四、基础语法

(一)变量

在 Go 语言中,变量的声明和赋值方式多样。例如:

package main
import{
    "fmt"
    "math"
}

func main(){
    var a = "start"
    var b, c int = 1, 2
    var d = true
    var e float64
    // 这里f的赋值语句有误,应该是f := float32(e)
    // g的赋值语句也有误,应该是g := a + "go"
    fmt.Println(a, b,c, d, e)
    // 定义常量
    const s string = "constant"
    const h = 3450000
    const t = 3e20/ h
    fmt.Println(s, h, math.Sin(h), math.Sin(t))
}

这里展示了不同类型变量(字符串、整数、布尔值、浮点数)的声明,以及常量的定义。需要注意代码中的错误部分,这也提醒我们在编写代码时要注意语法的正确性。

(二)If - else 语句

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 - else语句用于条件判断。在 Go 语言中,if语句可以包含一个简短的变量声明,这使得代码更加简洁。这里通过判断数字的奇偶性和大小范围,展示了if - else语句的多种用法。

(三)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 = i + 1
    }
}

for循环有多种形式。可以是无限循环(通过break跳出),也可以是传统的三段式for循环(初始化、条件判断、迭代)。continue语句用于跳过当前循环的剩余部分,直接进入下一次循环。这里的代码展示了for循环的各种特性。

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

switch语句用于多分支条件判断。可以是基于具体值的switch(如判断变量a的值),也可以是无表达式的switch(根据条件判断,这里根据时间判断是上午还是下午)。

(五)数组

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

数组在 Go 语言中有固定的长度。可以逐个元素赋值,也可以在声明时初始化。二维数组的初始化和访问通过嵌套的for循环实现,展示了数组在存储和处理数据方面的用法。

(六)切片

package main

import "fmt"

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

切片是一种动态大小的数据结构。通过make函数创建,使用append函数添加元素。copy函数用于复制切片内容。切片的截取操作可以获取子切片,方便对数据进行部分处理。

(七)集合(map)

package main

import "fmt"

func main() {
    m := make(map[string]int)
    m["one"] = 1
    m["two"] = 2
    fmt.Println(m)
    fmt.Println(len(m))
    fmt.Println(m["one"])
    fmt.Println(m["unknow"])
    r, ok := m["unknow"]
    fmt.Println(r, ok)
    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是 Go 语言中的键值对数据结构。通过make创建,使用键来访问和修改值。可以使用delete函数删除键值对。同时要注意map的遍历顺序是无序的。

(八)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)
        }
    }
    fmt.Println(sum)
    m := map[string]string{"a": "A", "b": "B"}
    for k, v := range m {
        fmt.Println(k, v)
    }
    for k := range m {
        fmt.Println("key", k)
    }
}

range关键字用于遍历数组、切片、map等数据结构。在遍历过程中,可以同时获取索引和值(对于数组和切片),或者键和值(对于map)。这为数据的遍历和处理提供了便捷的方式。

(九)函数

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)
    v, ok := exists(map[string]string{"a": "A"}, "a")
    fmt.Println(v, ok)
}

函数是 Go 语言中代码复用的基本单元。可以有多个参数和返回值。参数类型需要明确指定,不过对于相同类型的参数,可以省略部分类型声明(如add2函数)。函数可以返回多个值,这在处理一些需要同时返回结果和状态的情况时非常有用。

(十)指针

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

指针在 Go 语言中用于直接操作内存地址。通过&获取变量的地址,通过*解引用指针。这里对比了普通函数和使用指针的函数在修改参数值时的区别。

(十一)结构体

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
}

结构体是一种自定义的数据类型,可以将不同类型的变量组合在一起。结构体可以通过多种方式初始化,并且可以定义结构体相关的函数来操作结构体中的数据。这里展示了结构体的初始化和两种不同方式的密码检查函数(值传递和指针传递)。

(十二)结构体方法

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

结构体方法是与结构体相关联的函数。可以通过值接收者(如checkPassword方法)或指针接收者(如resetPassword方法)来定义。指针接收者可以修改结构体中的数据,而值接收者操作的是结构体的副本。

(十三)错误处理

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

错误处理在 Go 语言中通过返回值的方式实现。函数可以返回一个错误值,如果出现错误,可以在调用函数的地方进行处理。这里findUser函数在找不到用户时返回一个错误,调用者根据错误情况进行相应的操作。

(十四)字符串类型处理操作

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

Go 语言的strings包提供了丰富的字符串处理函数。包括判断字符串是否包含子串、计算子串出现的次数、判断前缀和后缀、查找子串位置、字符串连接、重复、替换、分割、大小写转换等操作。同时要注意字符串长度在不同编码下的计算方式(如对于中文字符串)。

(十五)字符串格式化

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

字符串格式化通过fmt.Printf等函数实现。可以将不同类型的数据按照指定的格式输出。例如%v用于输出值的默认格式,%+v可以输出结构体的字段名和值,%#v可以输出更详细的信息。对于浮点数,可以指定精度进行输出。

(十六)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)
}

Go 语言通过encoding/json包实现 JSON 数据的编码和解码。json.Marshal用于将结构体转换为 JSON 字符串,json.MarshalIndent可以格式化输出 JSON 字符串。json.Unmarshal则用于将 JSON 字符串解析为结构体。结构体中的标签(如json:"age")可以指定 JSON 中的键名。