GO语言入门笔记指南

2026-01-11 20:04:38

GO语言入门笔记指南

一.GO语言应用场景1.1 前言在学习GO语言的过程中会出一系类的go由浅入深的系列文章,敬请期待!

1.2 什么是GO语言Go语言是一门现代编程语言,规则简单,统一,优雅,吸收了若干编程语言的优点,解决了C,C++, Python等语言一些固有的难点问题

Go是一种过程编程语言,可用于快速机器代码编译。它是一种静态类型的编译语言。它提供了并发机制,可以轻松开发多核和联网的机器级程序。它是快速,动态类型和解释语言;它提供对接口和类型嵌入的支持。

Go语言是由Google的Robert Griesemer,Rob Pike和Ken Thompson 于2007年开发,但于2009年作为开源编程语言推出。

注:go语言源代码文件的扩展名必须是.go 。

image-20230115155837088GO语言的优点:

1高性能、高并发

2语法简单、学习曲线平缓

3丰富的标准库

Go具有强大的标准库,以包的形式分发。

4完善的工具链

5静态链接

Go是静态类型语言。因此,在这个编译器中,不仅可以成功编译代码,还可以确保类型转换和兼容性。由于这个特性,Go避免了我们在动态类型语言中遇到的所有问题。

6快速编译

7跨平台

Go语言就像Java语言一样,支持平台独立。由于其模块化设计和模块化,即代码被编译并转换为尽可能小的二进制形式,因此,它不需要依赖性。它的代码可以在任何平台上编译,也可以在任何服务器和应用程序上编译。

8垃圾回收

Go语言的设计者有意识地保持语言简单易懂。整个细节都在少量(一部分)页面中,并且通过语言中的面向对象支持做出了一些有趣的设计决策。对此,语言是固执的,并推荐一种实现事物的惯用方法。它更喜欢组合而不是继承。在Go语言中,“少花钱多办事”就是口头禅。

一个有开发经验的程序员,仅仅耗费一周就可以由学习阶段转到真正的开发阶段,完成一个高并发的应用开发。

1.3 仅仅10行完成高并发的服务器如下图

image-20230115162850213哪些公司在使用Go语言:

image-20230115195220871二.入门使用Goland,学生可以申请教育免费版:

image-202301151955390832.1 基础语法-HelloWorldHello World:

代码语言:go复制package main

import (

"fmt"

)

func main() {

fmt.Println("hello world,上进小菜猪")

}上述代码解释:

package main:程序的入口包。入口文件

import 的fmt控制输入输出文件:

import (

"fmt"

)

main函数调用了fmt的Println

运行结果:

image-202301152123232082.2 基础语法-变量类型2.2.1 变量声明变量:

1.使用var。

代码语言:go复制var a = "initial"

var b, c int = 1, 2

var d = true2.使用变量名:=值。

代码语言:go复制f := float32(e)

g := a + "foo"GO会更具上下文的类型来自动确定类型。

3.例子

引用:fmt和math

代码语言:go复制import (

"fmt"

"math"

)main函数:

代码语言:go复制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))运行结果如下:

image-202301152133077122.2.2 if else1.if后面不需要写括号的:例如

代码语言:go复制if 7%2 == 0 {

fmt.Println("7 is even")

} else {

fmt.Println("7 is odd")

}2.import的简单写法:

代码语言:go复制import "fmt"3.main函数:

代码语言:go复制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")

}运行结果如下:

image-202301152135581222.2.3 循环go里面只有for循环,没有while循环,没有do while循环。

简单的for循环如下:

代码语言:go复制for {

fmt.Println("loop")

break

}可以使用经典的c语言里的for循环:

代码语言:go复制for j := 7; j < 9; j++ {

fmt.Println(j)

}也可以使用continue跳出循环:

代码语言:go复制for n := 0; n < 5; n++ {

if n%2 == 0 {

continue

}

fmt.Println(n)

}运行结果如下:

image-202301152139068722.2.4 switch分支结构和c、c++类似。

不同点:

c/c++如果没有break还会跑下面的同级分支,go则不会。

例子:

1.引入time时间库:

代码语言:go复制import (

"fmt"

"time"

)2.源码:

先给a赋值为2,然后循环下面的值,运行fmt.Println("two"),没有break语句也会跳出这个switch。

t := time.Now()使用time库,将现在的系统时间赋值给t,然后进行case条件分支,否则抛出It's after noon。

代码语言:go复制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")

}运行结果如下:

image-202301152144308432.2.5 数组先定义一个5个长度的数组,然后对第三个位置进行一个赋值,为100.

然后输出a2和a的数组长度。

代码语言:go复制var a [5]int

a[2] = 100

fmt.Println("get:", a[2])

fmt.Println("len:", len(a))运行结果如下:

image-20230115215007486定义数组的时候就给其赋值。然后输出b数组看一眼:

代码语言:go复制b := [5]int{1, 2, 3, 4, 5}

fmt.Println(b)输出效果如下:

image-20230115215109857二维数组:定义一个二维数组。使用双层循环对其赋值。

代码语言:go复制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)输出结果如下:

image-202301152152140382.2.6 切片定义一个数组,指定其类型为字符。3个空间大小。然后对其进行赋值,然后输出第3个位置,和数组长度,代码如下:

代码语言:go复制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代码运行结果如下:

image-20230115230403180数组追加,和pyrhon一样,使用append,但是注意,语法略微不同。

代码语言:go复制s = append(s, "d")

s = append(s, "e", "f")

fmt.Println(s) // [a b c d e f]输出结果如下:

image-20230115230604748数组的拷贝,使用copt函数,我们先创建一个空的c数组,申请一个大小。然后使用copy函数,将s数组拷贝到c数组。然后输出c数组查看一下效果:

代码语言:go复制c := make([]string, len(s))

copy(c, s)

fmt.Println(c) // [a b c d e f]输出结果如下:

image-20230115230715940切片:s2:5:第3个元素开始,到第5个之前(不包括第五个元素)

:5:开头到到第5个之前(不包括第五个元素)

s2::第3个元素开始,到最后一个元素。代码如下:

代码语言:go复制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]输出结果如下:

image-20230115230850133创建数组的时候,就进行赋值操作:

代码语言:go复制good := []string{"g", "o", "o", "d"}

fmt.Println(good) // [g o o d]输出结果如下:

image-202301152309179792.2.7 map创建一个map。使用make函数,键值对:string:int。对其进行赋值。

然后输出查看效果,打印长度。指定键,查看值。如下代码:

代码语言:go复制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输出结果如下:

image-20230115231225101加入ok来看看是否有键存在。如下代码:

代码语言:go复制r, ok := m["unknow"]

fmt.Println(r, ok) // 0 false输出结果如下:

image-20230115231400041删除键值对。使用delete函数,代码如下。

代码语言:go复制delete(m, "one")赋值案例:

代码语言:go复制m2 := map[string]int{"one": 1, "two": 2}

var m3 = map[string]int{"one": 1, "two": 2}

fmt.Println(m2, m3)输出结果如下:

image-202301152315275852.2.8 rangefor 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。

首先定义一个numw数组,对其赋值。定义sum用于统计累加和。使用for 循环的 range 格式对其进行迭代循。具体如下:

代码语言:go复制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输出结果如下:

image-20230115232013611for 循环的 range 格式对map的遍历案例如下:

代码语言:go复制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

}输出结果如下:

image-202301152321339442.2.9 函数go语言的函数,有一些区别。变量名在后面。

先看一下主函数:

代码语言:go复制res := add(1, 2)

fmt.Println(res) // 3然后看一下add函数,这个add函数的作用是返回俩个值相加的结果。

代码语言:go复制func add(a int, b int) int {

return a + b

}然后我们看一下返回多值的情况:

传入俩个参数,一个map,一个字符a。

代码语言:go复制v, ok := exists(map[string]string{"a": "A"}, "a")

fmt.Println(v, ok) // A True看一下exists的函数。这里接受俩个函数,m"a"存在,ok的值为ture。返回给主函数。

代码语言:go复制func exists(m map[string]string, k string) (v string, ok bool) {

v, ok = m[k]

return v, ok

}输出结果如下:

image-202301152337159732.2.10 指针go语言的指针功能非常有限,主要的功能是为了对传入的参数进行修改。

这里的传入的参数实际上是一个拷贝。拷贝+1是不起作用的。

代码语言:go复制func add2(n int) {

n += 2

}想要起作用只能采用指针类型:

代码语言:go复制func add2ptr(n *int) {

*n += 2

}为了类型匹配,调用的时候,需要加&:add2ptr(&n)

下面是main函数:

代码语言:go复制n := 5

add2(n)

fmt.Println(n) // 5

add2ptr(&n)

fmt.Println(n) // 7运行结果如下:

image-202301152358217402.2.11 结构体先定义一个结构体user,定义两个变量:name和password:

代码语言:go复制type user struct {

name string

password string

}定义结构体值的几个方法:

下面代码是4种对结构体类型的赋值方法,非常简单。如下:

代码语言:go复制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"输出来看一下:

代码语言:go复制fmt.Println(a, b, c, d) // {wang 1024} {wang 1024} {wang 1024} {wang 1024}运行结果如下:

image-20230116000237471使用函数:

普通函数(不使用指针。)

代码语言:go复制func checkPassword(u user, password string) bool {

return u.password == password

}使用指针:

代码语言:go复制func checkPassword2(u *user, password string) bool {

return u.password == password

}主函数,调用:

代码语言:go复制fmt.Println(checkPassword(a, "haha")) // false

fmt.Println(checkPassword2(&a, "haha")) // false运行结果如下:

image-202301160004299172.2.12 结构体方法这里先把a赋值一个user结构体类型,并且对其进行赋值。

代码语言:go复制a := user{name: "wang", password: "1024"}

a.resetPassword("2048")然后直接a.调用方法:

使用指针才能改变其结构体里的值。

代码语言:go复制func (u *user) resetPassword(password string) {

u.password = password

}检查一下结构体里的值是不是等于2048。

代码语言:go复制fmt.Println(a.checkPassword("2048")) // truecheckPassword函数的内容如下:

代码语言:go复制func (u user) checkPassword(password string) bool {

return u.password == password

}运行结果如下:

image-202301160013213602.2.13 错误处理导入依赖包:errors,代码如下:

代码语言:go复制import (

"errors"

"fmt"

)先看一下调用的findUser,我们先传入了应该数组,和一个字符串。

代码语言:go复制u, err := findUser([]user{{"wang", "1024"}}, "wang")findUser如下:

这个函数作用是检查结构体的值,是不是我们规定的难搞值,如果是的话返回return &u, nil。否则就是出错了。返回return nil, errors.New("not found"),将not found 写到日志里,代码如下:

代码语言:go复制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")

}在主函数里,如果err不是nil的话,说明出错了,我们输出错误日志看一眼。

代码语言:go复制if err != nil {

fmt.Println(err)

return

}输出u的name

代码语言:go复制fmt.Println(u.name) // wang来一个错误案例:

我们调用findUser,但是传入 "li",上面的代码当然会u.name != name,就会有日志存入,err,然后下面进入判断,输出err,代码如下:

代码语言:go复制if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {

fmt.Println(err) // not found

return

} else {

fmt.Println(u.name)

}运行结果如下:

image-202301160028098042.2.14 字符串操作导入依赖包:strings,代码如下:

代码语言:go复制import (

"fmt"

"strings"

)方法列表:

image-20230116003152125主函数代码,对字符串操作案例:

代码语言:go复制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运行结果如下:

image-202301160032379602.2.15 字符串格式化先分别定义一个字符串,整数,指针。分别打印一下,代码如下:

代码语言:go复制s := "hello"

n := 123

p := point{1, 2}

fmt.Println(s, n) // hello 123

fmt.Println(p) // {1 2}运行结果如下:

image-20230116003508388可以使用任意%v来输出任意的的数值。代码如下:

可以使用%+v来输出详细的数值。

可以使用%#v来输出更加详细的数值。

\n标识换行。

代码语言:go复制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}运行结果如下:

image-20230116003644089小数,规定位数,这里和c/c++一模一样。

代码语言:go复制f := 3.141592653

fmt.Println(f) // 3.141592653

fmt.Printf("%.2f\n", f) // 3.142.2.16 json处理导入依赖包: "encoding/json",代码如下:

代码语言:go复制import (

"encoding/json"

"fmt"

)定义一个结构体userInfo。

代码语言:go复制type userInfo struct {

Name string

Age int `json:"age"`

Hobby []string

}对其进行一个赋值操作。

代码语言:go复制a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}使用json的Marshal方法。我们先看一下Marshal方法:

代码语言:go复制func Marshal(v interface{}) ([]byte, error)从返回值我们可以看到,该函数有两个返回值,一个是传入参数v的json编码,类型为[]byte,另外一个就是error。

将结构体变量a转换为json,代码如下:

代码语言:go复制buf, err := json.Marshal(a)如果发送错误,输出错误日志:

代码语言:go复制if err != nil {

panic(err)

}我们如果直接输出的话,是一堆为编译的数字。我们输出需要将其转换为字符串(序列化)才能进行输出,代码如下:

代码语言:go复制fmt.Println(buf) // [123 34 78 97...]

fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]} 运行结果如下:

image-20230116005940222使用MarshalIndent:

代码语言:go复制func MarshalIndent(v any, prefix, indent string)([]byte, error)MarshalIndent 类似于 Marshal,但应用缩进来格式化输出。根据缩进嵌套,输出中的每个 JSON 元素都将在以前缀开头的新行开始,后跟一个或多个缩进副本。

代码语言:go复制buf, err = json.MarshalIndent(a, "", "\t")

if err != nil {

panic(err)

}

fmt.Println(string(buf))输出如下:

image-20230116010222214JSON解码函数Unmarshal:

代码语言:go复制func Unmarshal(data []byte, v interface{}) errorUnmarshal函数解析json编码的数据并将结果存入v指向的值。

Unmarshal和Marshal做相反的操作,必要时申请映射、切片或指针,有如下的附加规则:

要将json数据解码写入一个指针,Unmarshal函数首先处理json数据是json字面值null的情况。此时,函数将指针设为nil;否则,函数将json数据解码写入指针指向的值;如果指针本身是nil,函数会先申请一个值并使指针指向它。

要将json数据解码写入一个结构体,函数会匹配输入对象的键和Marshal使用的键(结构体字段名或者它的标签指定的键名),优先选择精确的匹配,但也接受大小写不敏感的匹配。

代码语言:go复制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"}}输出结果如下:

image-202301160104326162.2.17 时间处理导入依赖包: "time",代码如下:

代码语言:go复制import (

"fmt"

"time"

)获取当前的时间并且输出:

代码语言:go复制now := time.Now()

fmt.Println(now) 运行结果如下:

image-20230116010741028还可以自己构造一个时间,如下代码:

代码语言:go复制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然后进行一个输出,也可以指定输出年月日等等。代码运行结果截图如下:

image-20230116010915276代码格式化:

代码语言:go复制fmt.Println(t.Format("2006-01-02 15:04:05")) 我们指定输出格式,代码运行结果截图如下:

image-20230116011034079时间差:使用sub函数,可以得出俩个时间的时间差。

代码语言:go复制diff := t2.Sub(t)

fmt.Println(diff) // 1h5m0s

fmt.Println(diff.Minutes(), diff.Seconds()) // 65 3900代码运行结果截图如下:

image-20230116011128262time.Parse()函数

Go语言中的Parse()函数用于解析格式化的字符串,然后查找它形成的时间值。

官方api:

代码语言:go复制func Parse(layout, value string) (Time, error)在这里,layout通过以哪种方式显示参考时间(即定义为Mon Jan 2 15:04:05 -0700 MST 2006)来指定格式,如果它是该值的话。但是,先前定义的布局(例如UnixDate,ANSIC,RFC3339等)解释了标准时间以及参考时间的合适表示形式。并且value参数保存字符串。其中,从值中删除的元素假定为零,如果不可能为零,则假定为一。

返回值:它返回它表示的时间值。并且如果不存在时区指示符,则它会返回UTC时间。

代码语言:go复制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代码运行结果截图如下:

image-20230116011342067时间戳:

代码语言:go复制fmt.Println(now.Unix()) // 1648738080运行结果如下:

image-202301160114139862.2.18 数字解析导入依赖包:"strconv",代码如下:

代码语言:go复制import (

"fmt"

"strconv"

)可以使用ParseFloa或者ParseInt转换小数或者整数。

代码语言:go复制f, _ := strconv.ParseFloat("1.234", 64)

fmt.Println(f) // 1.234

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

fmt.Println(n) // 111上面代码整数的第二个参数代表转换数字的进制,这里是10进制。

如果是0的话就是自动转换。代码如下;

代码语言:go复制n, _ = strconv.ParseInt("0x1000", 0, 64)

fmt.Println(n) // 4096使用Atoi快速把字符串转换为数字:

代码语言:go复制n2, _ := strconv.Atoi("123")

fmt.Println(n2) // 123数字不合法处理:

代码语言:go复制n2, err := strconv.Atoi("AAA")

fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax运行结果如下:

image-202301160118540832.2.19 进程信息导入依赖包:"os"和"os/exec",代码如下:

代码语言:bash复制import (

"fmt"

"os"

"os/exec"

)输出命令行参数:

代码语言:go复制fmt.Println(os.Args)获取或者写入环境变量:

代码语言:go复制fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...

fmt.Println(os.Setenv("AA", "BB"))快速启动子进程,并且获得输入输出。

代码语言:go复制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运行结果如下:image-20230116012325957三.本文总结本文写了下面几大块:

什么是 G0语言Go 语言基本特征Go 语言应用优势G0语言入门开发环境-安装 GolangG0语言基础语法下篇我将撰写Go语言的实战应用的笔记,敬请期待!

最新发表
友情链接

Copyright © 2022 日本世界杯_林高远世界杯 - edenyn.com All Rights Reserved.