Go基础语法 | 青训营笔记

274 阅读1分钟

这是我参与「第五届青训营 」笔记创作活动的第1天

一. 基础结构

package main
  • 此文件属于main包的一部分,main包是程序的入口包,此文件也就是程序的入口文件
import (
    "fmt"
)
  • 导入标准库中的“format”包(用于字符串的 IO 和格式化)
go run foldername/filename.go
// or
go build foldername/filename.go
./filename.go
  • 运行go文件
graph LR
Package --> import --> func 

二. 基础语法

  1. 强类型语言:可以修改变量定义的类型
    • 字符串是内置类型,可以直接用+进行拼接,用==比较两个字符串
    • const常量没有确定的类型,根据使用的上下文自动确定类型,对应的是var的定义(常用:=
  2. 循环:没有whiledo-while循环,只有for循环
  3. 分支(条件)
    • if-else—— if 后的条件没有( )小括号限制,内容必有大括号{ }
    • switch—— 不用加break截断分支,找到数值并做输出后,自动跳出分支;可以使用任意变量类型,比如字符串、结构体;可以取代任意的if-else语句
    t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("It's before noon")
	default:
		fmt.Println("It's after noon")
	}
  1. 数组:具有编号长度固定的元素**序列,真实情况很少用数组,更多用切片(可变长度,任意时刻更改长度),**可以像数组一样往其中写或存储值,用append追加元素,扩容需要重新赋值
// 扩容
s = append(s, "plus")
// 拷贝
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)
// 像python一样的切片操作(左闭右开),但不支持负数的处理,需要用len取出长度,再做简单运算、
fmt.Println(s[2:5])
  1. map(哈希或字典):使用最频繁的数据结构,完全无序,不会按照字母和插入顺序输出,偏随机顺序
// 用make创建一个空map —— key和value [KV 键值对]
m := make(map[string]int)
m["one"] = 1 // 创建KV
delete(m, "one") // 删除KV
// ok查看KV是否存在
r, ok := m["unknown"]
fmt.Println(r, ok)
  • 对于一个slice or map可以用range快速遍历
// 对于数组:i 可以 替换为 _ ,实现索引遍历的过滤
	for i, num := range nums {
		sum += num
		if num == 2 {
			fmt.Println("index:", i, "num:", num) // index: 0 num: 2
		}
	}
// 对于map,k和v任选
	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)
	}
  1. 函数
    • 定义参数的变量类型后置
    • 原生支持返回多个值,一般两部分(真正返回结果;错误信息)
func exists(m map[string]string, k string) (v string, ok bool) {
	v, ok = m[k]
	return v, ok
}

	v, ok := exists(map[string]string{"a": "A"}, "a")
	fmt.Println(v, ok) // A True
  1. 指针:比较初级,主要针对参数修改
package main

import "fmt"

// Copy版本,无法修改实际值
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
}
  1. 结构体:带类型字段集合
    • 用结构体的名称初始化所定义的变量
    • 没有初始化就是空值:数值就是0,字符串是空字符串
    • 可以作为函数的参数,再加上指针定义,就可以直接对结构体进行修改,也可以减少大结构体拷贝的开销
    • 为结构体定义方法,相对于类成员函数
// 从一个普通函数,改造成结构体方法(类成员函数)
func (u user) checkPassword(password string) bool {
	return u.password == password
}

// 也可以带指针,修改结构体内变量的值
func (u *user) resetPassword(password string) {
	u.password = password
}
  1. 字符串:strings包有很多快捷接口可以调用
    • Printf: 格式化的%v可以代替C%d, %s等各种具体类型 (\n同样负责换行;+, # more detailed)
	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
  1. JSON 处理:保证已有结构体每个字段名称都是大写,就可以用json.Marshal()序列化成一个数组,本质是字符串(用string()强制类型转换才能打印出字符串,否则打印出16进制编码)

    • 序列化后,还可以反序列化到一个空的变量
  2. 时间处理

  • 在和某些系统交互的时候,经常用到时间戳,需要使用Unix()
  • 2006-01-02 15:04:05是固定时间格式的表达,内容固定
	t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
	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
  1. 字符串和数字的转化
  • 字符串
  • 进制
  • 位数(精度)
	n, _ := strconv.ParseInt("111", 10, 64)
	fmt.Println(n) // 111

// 进制处为0时自动判断进制
	n, _ = strconv.ParseInt("0x1000", 0, 64)
	fmt.Println(n) // 4096

// 相当于ParseInt("123",10,0)
	n2, _ := strconv.Atoi("123")
	fmt.Println(n2) // 123

	n2, err := strconv.Atoi("AAA")
	fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax

// Itoa 实现十进制转化为字符串,没有error
	n3 := strconv.Itoa(12)
	fmt.Println(n3)
	fmt.Printf("%T, %v\n", n3, n3)
  1. 进程信息
import (
	"fmt"
	"os"
	"os/exec"
)

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

三. 小结

语法简洁,和python大部分逻辑很相似

标准库效率优化,而且error和panic异常处理分明,代码易读,提高开发和迭代效率

四. 参考