语言上手-基础语言 | 青训营笔记

71 阅读8分钟

Go 语言上手-基础语言 | 青训营笔记

Go语言特性

  1. 高性能、内嵌对高并发的支持
  2. 语法简单、学习曲线平缓
  3. 丰富的标准库(官方库的 API 几乎可以保证能与 Go 版本的迭代一直兼容)
  4. 完善的工具链
  5. 静态链接
  6. 快速编译
  7. 跨平台
  8. 垃圾回收

基础语法

文件属于main包的一部分,main包是程序的入口包(package main)。 导入标准库的fmt包,用来输入、输出、格式化字符串(import "fmt") 注:鼠标悬浮在函数上能够查看函数文档;

变量类型

常见的变量类型包括字符串、整数、浮点型、布尔型。 字符串:内置类型可以通过+拼接也可以用+=去拼接(多行拼接需要),=去比较。字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。

var str string // 声明字符串变量 
str = "Hello World" // 变量初始化 
str2 := "你好呀" // 也可以同时进行声明和初始化

const s string = "constant" //常量定义,常量在golang里面没有确定的类型,会根据使用的上下文自自动确定类型。

字符串两种表示形式 双引号, 会识别转义字符(\n:换行符 \r:回车符 \t:tab 键 \u 或 \U:Unicode 字符 \:反斜杠自身) 反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防攻击、输出源代码等效果

var str = "Hello \n World " //双引号识别转义字符
var codeStr = `function matchwo(a,b){
    if a<b && a<0 {
        return 1
    }else{
        return 0
    } \n 原样输出
}
` //反引号,以字符串的原生形式输出

if else

关键字 if 和 else 之后的左大括号{必须和关键字在同一行,如果你使用了 else if 结构,则前段代码块的右大括号}必须和 else if 关键字在同一行,这两条规则都是被编译器强制规定的。

var ten int = 11
if ten > 10 {
    fmt.Println(">10")
} else {
    fmt.Println("<=10")
}

if 还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断,代码如下:

if err := Connect(); err != nil { //Connect 是一个带有返回值的函数,err:=Connect() 是一个语句,执行 Connect 后,将错误保存到 err 变量中。
    fmt.Println(err)
    return
}//这种写法可以将返回值与判断放在一行进行处理,而且返回值的作用范围被限制在 if、else 语句组合中。

循环

for循环

for {
           // 无限循环下去
        }

For-each range 循环

numbers := [6]int{1235}
        for i,x:= range numbers {
                fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
        }

switch

Go语言改进了 switch 的语法设计,case 与 case 之间是独立的代码块,不需要通过 break 语句跳出当前 case 代码块以避免执行到下一行。示例:

var a = "hello"
switch a {
case "hello":
    fmt.Println(1)
case "world":
    fmt.Println(2)
default:
    fmt.Println(0)
}

上面例子中,每一个 case 均是字符串格式,且使用了 default 分支,Go语言规定每个 switch 只能有一个 default 分支。 case 后不仅仅只是常量,还可以和 if 一样添加表达式,也可以时多个值,一分支多值。

数组

数组的声明

var 数组变量名 [元素数量]Type

语法说明如下所示: 数组变量名:数组声明及使用时的变量名。 元素数量:数组的元素数量,可以是一个表达式,但最终通过编译期计算的结果必须是整型数值,元素数量不能含有到运行时才能确认大小的数值。 Type:可以是任意基本类型,包括数组本身,类型为数组本身时,可以实现多维数组。 数组的每个元素都可以通过索引下标来访问,索引下标的范围是从 0 开始到数组长度减 1 的位置,内置函数 len() 可以返回数组中元素的个数。

切片

切片默认指向一段连续内存区域,可以是数组,也可以是切片本身。从连续内存区域生成切片是常见的操作,格式如下:

slice [开始位置 : 结束位置]

语法说明如下: slice:表示目标切片对象; 开始位置:对应目标切片对象的索引; 结束位置:对应目标切片的结束索引。 如果需要动态地创建一个切片,可以使用 make() 内建函数,格式如下:

make( []Type, size, cap )

其中 Type 是指切片的元素类型,size 指的是为这个类型分配多少个元素,cap 为预分配的元素数量,这个值设定后不影响 size,只是能提前分配空间,降低多次分配空间造成的性能问题。

map

Go语言中 map 是一种特殊的数据结构,一种元素对(pair)的无序集合,pair 对应一个 key(索引)和一个 value(值),所以这个结构也称为关联数组或字典,这是一种能够快速寻找值的理想结构,给定 key,就可以迅速找到对应的 value。 map 是引用类型,可以使用如下方式声明:

var mapname map[keytype]valuetype

其中: mapname 为 map 的变量名。 keytype 为键类型。 valuetype 是键对应的值类型。

和数组不同,map 可以根据新增的 key-value 动态的伸缩,因此它不存在固定长度或者最大限制,但是也可以选择标明 map 的初始容量 capacity,格式如下:

map2 := make(map[string]float, 100)

range

关键字 range,它可以配合关键字 for 来迭代切片里的每一个元素。

  // 创建一个整型切片,并赋值
  slice := []int{10, 20, 30, 40}
  // 迭代每一个元素,并显示其值
  for index, value := range slice {
  fmt.Printf("Index: %d Value: %d\n", index, value)
  }

函数

函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段,其可以提高应用的模块性和代码的重复利用率。函数本身可以作为值进行传递。支持匿名函数和闭包(closure)。函数可以满足接口。函数可以有多个返回值。 函数声明包括函数名、形式参数列表、返回值列表(可省略)以及函数体。

func 函数名(形式参数列表)(返回值列表){
    函数体
}

指针

一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值为 nil。指针变量通常缩写为 ptr。 每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作),格式如下:

ptr := &v    // v 的类型为 T

其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收,ptr 的类型为*T,称做 T 的指针类型,*代表指针。

结构体

Go 语言通过用自定义的方式形成新的类型,结构体是类型中带有成员的复合类型。Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性。结构体成员是由一系列的成员变量构成,这些成员变量也被称为“字段”。字段有以下特性:字段拥有自己的类型和值;字段名必须唯一;字段的类型也可以是结构体,甚至是字段所在结构体的类型。

错误处理

在Go语言中符合语言习惯的做法就是使用一个单独的返回值来返回错误的信息。并且只能用if else来简单的处理。

字符串操作

在标准库 strings 包里面有很多常用的字符串工具函数,比如contains判断一个字符串里面是否有包含另一个字符串,count字符串计数,index查找某个字符串的位置。join连接多个字符串repeat重复多个字符串replace替换字符串。

json处理

go语言 里面的 JSON 操作非常简单,对于一个已有的结构体,我们可以什么都不做,只要保证每个字段的第一个字母是大写,也就是是公开字段。那么这个结构体就能用 JSON.marshaler 去序列化,变成一个 JSON 的字符串。 序列化之后的字符串也能够用 JSON.unmarshaler 去反序列化到一个空的变量里面。 这样默认序列化出来的字符串的话,它的风格是大写字母开头,而不是下划线。我们可以在后面用 json tag 等语法来去修改输出 JSON 结果里面的字段名。

进程信息

在 go 里面,我们能够用 os.argv 来得到程序执行的时候的指定的命令行参数。 比如我们编译的一个 二进制文件,command。 后面接 abcd 来启动,输出就是 os.argv 会是一个长度为 5 的 slice ,第一个成员代表二进制自身的名字。我们可以用 so.getenv来读取环境变量。

总结

在本章中切片和数组这两个概念极易混淆,和数组对应的类型是切片,切片是可以增长和收缩的动态序列,功能也更灵活,但是想要理解切片工作原理的话需要先理解数组。 本章中较难掌握的知识点我认为是结构体和指针,结构体中的结构体方法类似其它语言的类函数。