Go语言基础入门|青训营笔记

121 阅读7分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记

Go语言基础:字节青训营

Go语言简介

Go语言(或 Golang)起源于 2007 年,并在 2009 年正式对外发布。Go 是非常年轻的一门语言,它的主要目标是“兼具 Python 等动态语言的开发速度和 C/C++ 等编译型语言的性能与安全性”。

Go语言是编程语言设计的又一次尝试,是对类C语言的重大改进,它不但能让你访问底层操作系统,还提供了强大的网络编程和并发编程支持。Go语言的用途众多,可以进行网络编程、系统编程、并发编程、分布式编程。

Go的特点和优点

  1. 高性能,高并发
  2. 语法简单,学习曲线平缓.Go 从零开始,没有历史包袱,在汲取众多经验教训后,可从头规划一个规则严谨、条理简单的世界。
  3. 丰富的标准库
  4. 完善的工具链
  5. 静态链接
  6. 快速编译
  7. 跨平台
  8. 垃圾回收

Go语言开发环境推荐

1) Goland

Goland 是由 JetBrains 公司开发的一个新的商业 IDE,旨在为 Go 开发者提供的一个符合人体工程学的新的商业 IDE。Goland 整合了 IntelliJ 平台(一个用于 java 语言开发的集成环境,也可用于其他开发语言),提供了针对Go语言的编码辅助和工具集成。

2) Visual Studio Code(简称VS Code)

是一款由微软公司开发的,能运行在 Mac OS X、Windows 和 Linux 上的跨平台开源代码编辑器。

VScode 安装教程参见:www.runoob.com/w3cnote/vsc…

从扩展管理中安装Go插件

打开 VSCode 的扩展

搜索go插件并安装

配置包管理器Go MOD镜像

go module 是Go语言从 1.11 版本之后官方推出的版本管理工具 类似于pip,国内很多包的下载效果都不好,需要配置镜像代理

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
​
# 清空缓存 
go clean --modcache
​
# 查看环境信息
go env

Go语言的基础语法

1. hello world

package main
​
import (
    "fmt"
)
​
func main() {
    fmt.Println("hello world")
}
​

要运行这个程序,将这些代码放到 hello-world.go 中并且使用 go run 命令。

2.变量

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

var 声明 1 个或者多个变量。

var a string = "initial"
fmt.Println(a)

可以申明一次性声明多个变量。

var b, c int = 1, 2
fmt.Println(b, c)

Go 将自动推断已经初始化的变量类型。

var d = true
fmt.Println(d)

声明变量且没有给出对应的初始值时,变量将会初始化为零值 。例如,一个 int 的零值是 0。

var e int
fmt.Println(e)

:= 语句是申明并初始化变量的简写

f := float32(e)

3. if else

	if 7%2 == 0 {
        fmt.Println("7 is even")
    } else {
        fmt.Println("7 is odd")
    }

4.循环

	i := 1
    for i <= 3 {
        fmt.Println(i)
        i = i + 1
    }	

5.switch

最常用的方式,带单个循环条件。

   i := 1
    for i <= 3 {
        fmt.Println(i)
        i = i + 1
    }

不带条件的 for 循环将一直执行,直到在循环体内使用了 break 或者 return 来跳出循环

	for {
        fmt.Println("loop")
        break
    }

6.数组

 	var a [5]int
    fmt.Println("emp:", a)//创建了一个数组 a 来存放刚好 5 个 int
    a[1] = 100//我们可以使用 array[index] = value 语法来设置数组指定位置的值
    fmt.Println("set:", a)
    fmt.Println("get:", a[1])//用 array[index] 得到值
    fmt.Println("len:", len(a))	//使用内置函数 len 返回数组的长度

7. 切片

s := make([]string, 3)//slice 的类型仅由它所包含的元素决定(不像数组中还需要元素的个数)。要创建一个长度非零的空slice,需要使用内建的方法 make。这里我们创建了一个长度为3的 string 类型 slice(初始化为零值)。
fmt.Println("emp:", s)

s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("set:", s)
fmt.Println("get:", s[2])
fmt.Println("len:", len(s))//len 返回 slice 的长度
 s = append(s, "d")//slice 支持比数组更多的操作。其中一个是内建的 append,它返回一个包含了一个或者多个新值的 slice

8.map

	m := make(map[string]int)
	m["one"] = 1 //使用典型的 make[key] = val 语法来设置键值对
	m["two"] = 2
	fmt.Println(m)           // map[one:1 two:2]  使用例如 Println 来打印一个 map 将会输出所有的键值对。
	fmt.Println(len(m))      // 2       //当对一个 map 调用内建的 len 时,返回的是键值对数目
	fmt.Println(m["one"])    // 1       //使用 name[key] 来获取一个键的值
	fmt.Println(m["unknow"]) // 0

9.range

	nums := []int{2, 3, 4}//使用 range 来统计一个 slice 的元素个数
	sum := 0
	for i, num := range nums {
		sum += num
		if num == 2 {
			fmt.Println("index:", i, "num:", num) // index: 0 num: 2
		}
	}

10函数

package main

import "fmt"

func add(a int, b int) int {   //这里是一个函数,接受两个 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) {//(string, bool) 在这个函数中标志着这个函数返回 2 个值
	v, ok = m[k]
	return v, ok
}

func main() {
	res := add(1, 2)//通过 name(args) 来调用一个函数
	fmt.Println(res) // 3

	v, ok := exists(map[string]string{"a": "A"}, "a")
	fmt.Println(v, ok) // A True
}

11.指针

func add2(n int) {
	n += 2
}

func add2ptr(n *int) {
	*n += 2
}

func main() {
	n := 5
	add2(n)
	fmt.Println(n) // 5
	add2ptr(&n)//通过 &n 语法来取得 n 的内存地址
	fmt.Println(n) // 7
}

12.结构体

type user struct {
	name     string
	password string
}
//这里的 user 结构体包含了 name 和 password 两个字段

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
}

13.错误处理

type user struct {
	name     string
	password string
}

func findUser(users []user, name string) (v *user, err error) {//按照惯例,错误通常是最后一个返回值并且是 error 类型
	for _, u := range users {
		if u.name == name {
			return &u, nil//返回错误值为 nil 代表没有错误
		}
	}
	return nil, errors.New("not found")//errors.New 构造一个使用给定的错误信息的基本error 值
}

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

14.字符串操作

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
}

15.字符串格式化

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
}

16.Json处理

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

17.数字解析

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
}

18 进程

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程序

使用Go命令编译执行Go程序的例子

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

编译执行

Go指令

可以
go build hello.go
./hello.exe

也可以
go run hello.go

也可以添加VSCode环境,直接使用

包管理

  每个go程序都由包构成的,程序从main包的main函数开始运行。编译不包含main包的源文件后,不会得到可执行文件 不同包的源程序需要通过import关键字导入别的包 import 的是目录,建议绝对路径:import “包的路径”。


单行导入:
import "fmt"

多行导入:
import (

  “包1的路径”

  “包2的路径”
)