当前位置:网站首页>Go 学习笔记
Go 学习笔记
2022-06-22 04:05:00 【Looooking】
最近一直接触的是 Python, Ruby 之类的解释性语言,至于静态语言和动态语言的优劣,这儿就不多分析了。如果现阶段想要熟练掌握一门静态语言,感觉 Go 应该是不错的选择,如果有 C++ 、Java 的语言基础,相信上手应该也会很快。
基本结构和数据类型
关键字和标识符
Go 代码中会使用到的关键字:
| break | default | func | interface |
| case | defer | go | map |
| chan | else | goto | package |
| const | fallthrough | if | range |
| continue | for | import | return |
Go 代码中会使用到的标识符:
| append | bool | byte | cap | close | complex |
| copy | false | float32 | float64 | imag | int |
| int32 | int64 | iota | len | make | new |
| println | real | recover | string | true |
基本结构和要素
可见性规则
当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 private )。
Hello World
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}注释
注释和 C++ 的一样,可以使用 // 进行单行注释,可以使用 /* ... */ 进行块注释。
类型及转换
使用 var 声明的变量的值会自动初始化为该类型的零值。类型定义了某个变量的值的集合与可对其进行操作的集合。
类型可以是基本类型,如:int、float、bool、string;结构化的(复合的),如:struct、array、slice、map、channel;只描述类型的行为的,如:interface。
在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值。由于 Go 语言不存在隐式类型转换,因此所有的转换都必须显式说明,就像调用一个函数一样。
package main
import "fmt"
func main() {
a := 5.0
b := int(a)
fmt.Println(b)
}
一般结构
- 在完成包的 import 之后,开始对常量、变量和类型的定义或声明。
- 如果存在 init 函数的话,则对该函数进行定义(这是一个特殊的函数,每个含有该函数的包都会首先执行这个函数)。
- 如果当前包是 main 包,则定义 main 函数。
- 然后定义其余的函数,首先是类型的方法,接着是按照 main 函数中先后调用的顺序来定义相关函数,多个函数,可以按照字母顺序来进行排序。
常量
常量的值必须是能够在编译时就能够确定的。因为在编译期间自定义函数均属于未知,因此无法用于常量的赋值,但内置函数可以使用。
常量定义
语法:
const identifier [type] = value常量使用关键字 const 定义,用于存储不会改变的数据。存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
const Pi = 3.14159隐式与显式
编译器可以根据变量的值来推断其类型。
显式类型定义:
const b string = "abc"隐式类型定义:
const b = "abc"
并行赋值
package main
import "fmt"
const beef, two = "meet", 2
const (
Monday, Tuesday, Wednesday = 1, 2, 3
Thursday, Friday, Saturday = 4, 5, 6
)
const (
Unknown = 0
Male = 1
Female = 2
)
const (
RED int = iota
ORANGE
YELLOW
GREEN
BLUE
INDIGO
VIOLET
)
func main() {
fmt.Println(Wednesday)
fmt.Println(Male)
fmt.Println(YELLOW)
}
变量
声明
Go声明变量时将变量的类型放在变量的名称之后,声明形式相比 C 而言更加清晰。
语法:
var identifier type当一个变量被声明之后,系统自动赋予它该类型的零值:int 为 0,float 为 0.0,bool 为 false,string 为空字符串,指针为 nil。
package main
import "fmt"
var (
a int
b bool
c string
)
func main() {
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
}
0
false
赋值
一般情况下,只有类型相同的变量之间才可以相互赋值。声明与赋值(初始化)语句也可以组合起来。
package main
import "fmt"
var (
a int = 1
b bool = true
c string = "hello"
)
func main() {
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
}1
true
hello简短赋值
简短赋值是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。使用操作符 := 可以高效地创建一个新的变量,称之为初始化声明。
如果在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明。
如果声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误。
package main
import "fmt"
func main() {
var a int = 1
b := 2
fmt.Println(a)
fmt.Println(b)
}
init 函数
package main
import (
"fmt"
"math"
)
var Pi float64
func init() {
Pi = 4 * math.Atan(1)
}
func main() {
fmt.Println(Pi)
}
基本类型
布尔类型
布尔型的值只可以是常量 true 或者 false。两个类型相同的值可以使用相等 == 或者不等 != 运算符来进行比较并获得一个布尔型的值。
Go 对于值之间的比较有非常严格的限制,只有两个类型相同的值才可以进行比较。像下面这种是会报错的哟。
package main
import "fmt"
func main() {
a := true
b := "hello"
if a == b {
fmt.Println("a equal to b")
}
}
# command-line-arguments
.\test.go:8:7: invalid operation: a == b (mismatched types bool and string)
Compilation finished with exit code 2&& 和 || 是具有快捷性质的运算符(大部分语言都是有这个特性的,比如 Ruby,或者 Python 的 and 和 or),当运算符左边表达式的值已经能够决定整个表达式的值的时候(&& 左边的值为 false,|| 左边的值为 true),运算符右边的表达式将不会被执行。利用这个性质,如果你有多个条件判断,应当将计算过程较为复杂的表达式放在运算符的右侧以减少不必要的运算。
数字类型
Go 语言支持整型和浮点型数字,包括基于架构的类型。例如:int、uint 和 uintptr。
与操作系统架构无关的类型都有固定的大小,并在类型的名称中就可以看出来:
整数:
- int8(-128 -> 127)
- int16(-32768 -> 32767)
- int32(-2,147,483,648 -> 2,147,483,647)
- int64(-9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807)
无符号整数:
- uint8(0 -> 255)
- uint16(0 -> 65,535)
- uint32(0 -> 4,294,967,295)
- uint64(0 -> 18,446,744,073,709,551,615)
浮点型(IEEE-754 标准):
- float32(+- 1e-45 -> +- 3.4 * 1e38)
- float64(+- 5 * 1e-324 -> 107 * 1e308)
Go 中不允许不同类型之间的混合使用(除非通过显式转换),但是对于常量的类型限制非常少,因此允许常量之间的混合使用。
package main
func main() {
var a int
var b int32
a = 15
b = b + a // 编译错误
b = b + 5 // 因为 5 是常量,所以可以通过编译
}在格式化字符串里,%t 来表示你要输出的值为布尔型,%d 用于格式化整数(%x 和 %X 用于格式化 16 进制表示的数字),%g 用于格式化浮点型(%f 输出浮点数,%e 输出科学计数表示法),%0d 用于规定输出定长的整数,其中开头的数字 0 是必须的。%n.mg 用于表示数字 n 并精确到小数点后 m 位,除了使用 g 之外,还可以使用 e 或者 f,例如:使用格式化字符串%5.2e 来输出 3.4 的结果为 3.40e+00。
关于更多 Go 格式化输出的内容,可参考:Go语言格式化输出_General_zy的博客-CSDN博客_go 格式化输出
数字值转换
当进行类似 a32bitInt = int32(a32Float) 转换时,小数点后的数字将被丢弃。这种情况一般发生当从取值范围较大的类型转换为取值范围较小的类型时。
字符类型
在 Go 中,字符只是整数的特殊用例。byte 类型是 uint8 的别名,对于只占用 1 个字节的传统 ASCII 编码的字符来说,完全没有问题。例如:var ch byte = 'A';字符使用单引号括起来。格式化说明符 %c 用于表示字符;当和字符配合使用时,%v 或 %d 会输出用于表示该字符的整数;%U 输出格式为 U+hhhh 的字符串。
var ch byte = 65 或 var ch byte = '\x41'字符串
解释字符串
该类字符串使用双引号括起来,其中的相关的转义字符将被替换,这些转义字符包括:
\n:换行符\r:回车符\t:tab 键\u或\U:Unicode 字符\\:反斜杠自身
非解释字符串
该类字符串使用反引号(其他解释型语言会使用单引号)括起来,例如:
`This is a raw string \n` 中的 `\n\` 会被原样输出。package main
import "fmt"
func main() {
fmt.Println("hello\nworld")
fmt.Println(`hello\nworld`)
}hello
world
hello\nworld
len() 来获取字符串所占的字节长度,而不是字符串的长度!!!(字符串长度获取另有其方法)
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
str1 := "asSASA ddd dsjkdsjsこん dk"
fmt.Println(len(str1))
fmt.Println(utf8.RuneCountInString(str1))
}28
24字符串拼接
+ 号 或者 strings.Join()
strings
前后缀
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.HasPrefix("hello world", "hello"))
fmt.Println(strings.HasSuffix("hello world", "world"))
}true
true包含关系
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Contains("hello world", "o w"))
}true字符串索引
Indx、LastIndex
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Index("hello world", "o"))
fmt.Println(strings.LastIndex("hello world", "o"))
}4
7字符串替换
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Replace("hello world", "l", "x", 2))
fmt.Println(strings.Replace("hello world", "l", "x", -1))
}hexxo world
hexxo worxd字符串统计
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Count("hello world", "l"))
}3字符串重复
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Repeat("hello ", 3))
}hello hello hello字符串大小写
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.ToLower("Hello World"))
fmt.Println(strings.ToUpper("Hello World"))
}hello world
HELLO WORLD字符串修剪
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.TrimSpace(" Hello World "))
fmt.Println(strings.TrimLeft(" Hello World ", " "))
fmt.Println(strings.TrimRight(" Hello World ", " "))
fmt.Println(strings.Trim("Hello World", "old"))
}Hello World
Hello World
Hello World
Hello Wor字符串分割
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Fields("hello world"))
fmt.Println(strings.Fields("hello world")) // 类似于 Ruby 的 split
fmt.Println(strings.Split("hello world", " "))
fmt.Println(strings.Split("hello world", " ")) // 类似于 Python 的 split(" ")
// "hello world".split(" ")
// ['hello', '', '', 'world']
}[hello world]
[hello world]
[hello world]
[hello world]字符串拼接
package main
import (
"fmt"
"strings"
)
func main() {
str1 := strings.Fields("hello world")
fmt.Println(strings.Join(str1, "-"))
}hello-world字符串读取
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.NewReader("hello world"))
}&{hello world 0 -1}strconv
package main
import (
"fmt"
"strconv"
)
func main() {
var orig string = "666"
var an int
var newS string
fmt.Printf("The size of ints is: %d\n", strconv.IntSize)
an, _ = strconv.Atoi(orig)
fmt.Printf("The integer is: %d\n", an)
an = an + 5
newS = strconv.Itoa(an)
fmt.Printf("The new string is: %s\n", newS)
}The size of ints is: 64
The integer is: 666
The new string is: 671时间和日期
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t.YearDay())
fmt.Println(t.Year())
fmt.Println(t.Month())
fmt.Println(t.Day())
fmt.Println(t.Date())
fmt.Println(t.Unix())
fmt.Println(t.Format(time.RFC1123))
fmt.Println(t.Format("2006-01-02 03:04:05"))
}171
2022
June
20
2022 June 20
1655693632
Mon, 20 Jun 2022 10:53:52 CST
2022-06-20 11:05:39指针
一个指针变量可以指向任何一个值的内存地址 它指向那个值的内存地址,在 32 位机器上占用 4 个字节,在 64 位机器上占用 8 个字节,并且与它所指向的值的大小无关。Go 语言中的指针保证了内存安全。
package main
import "fmt"
func main() {
var i int = 5
var ptr *int
ptr = &i
fmt.Println(i, *ptr, ptr)
*ptr = 6 // 通过 *ptr 可以修改原始对象的值
fmt.Println(i, *ptr, ptr)
}5 5 0xc00000a098
6 6 0xc00000a098控制结构
关键字 if 和 else 之后的左大括号必须和 else-if 关键字在同一行。这两条规则都是被编译器强制规定的。
if-else
if
if condition {
// do something
}if-else
if condition {
// do something
} else {
// do something
}if-else if
if condition1 {
// do something
} else if condition2 {
// do something else
}else {
// catch-all or default
}if initialization; condition
这种写法具有固定的格式(在初始化语句后方必须加上分号)。
if initialization; condition {
// do something
}如果变量在 if 结构之前就已经存在,那么在 if 结构中,该变量原来的值会被隐藏(局部变量优先原则)。
package main
import (
"fmt"
)
func main() {
var i int = 10
if i := 5; i == 5 {
fmt.Println("i ==", i)
} else {
fmt.Println("i != 5")
}
fmt.Println("i ==", i)
}i == 5
i == 10函数返回值
Go 语言的函数经常使用两个返回值来表示执行是否成功:返回某个值以及 true 表示成功;返回零值(或 nil)和 false 表示失败。当不使用 true 或 false 的时候,也可以使用一个 error 类型的变量来代替作为第二个返回值:成功执行的话,error 的值为 nil,否则就会包含相应的错误信息(Go 语言中的错误类型为 error: var err error)。这样一来,就很明显需要用一个 if 语句来测试执行结果;由于其符号的原因,这样的形式又称之为 comma,ok 模式(pattern)。
normal
package main
import (
"fmt"
"strconv"
)
func main() {
var orig string = "666"
// var an int
var newS string
// var err error
fmt.Printf("The size of ints is: %d\n", strconv.IntSize)
// anInt, err = strconv.Atoi(origStr)
an, err := strconv.Atoi(orig)
if err != nil {
fmt.Printf("orig %s is not an integer - exiting with error\n", orig)
return
}
fmt.Printf("The integer is %d\n", an)
an = an + 5
newS = strconv.Itoa(an)
fmt.Printf("The new string is: %s\n", newS)
}The size of ints is: 64
The integer is 666
The new string is: 671error
package main
import (
"fmt"
"strconv"
)
func main() {
var orig string = "ABC"
// var an int
var newS string
// var err error
fmt.Printf("The size of ints is: %d\n", strconv.IntSize)
// anInt, err = strconv.Atoi(origStr)
an, err := strconv.Atoi(orig)
if err != nil {
fmt.Printf("orig %s is not an integer - exiting with error\n", orig)
return
}
fmt.Printf("The integer is %d\n", an)
an = an + 5
newS = strconv.Itoa(an)
fmt.Printf("The new string is: %s\n", newS)
}The size of ints is: 64
orig ABC is not an integer - exiting with error习惯用法
if err := file.Chmod(0664); err !=nil {
fmt.Println(err)
return err
}
//------------------------------------
if value, ok := readData(); ok {
…
}
//------------------------------------
func atoi (s string) (n int) {
//1、如果返回多个值是,在接受时,希望忽略某个返回值,则使用_符号占位忽略。
//2、如果返回值只有一个(返回值类型列表)可以不写()
n, _ = strconv.Atoi(s)
return
}
边栏推荐
- Window common shortcut keys
- Some journals of C51
- Bubble sort
- 【BP回归预测】基于matlab GA优化BP回归预测(含优化前的对比)【含Matlab源码 1901期】
- Use of markdown markup language
- About calling EditText in dialog
- 在线文本按行批量反转工具
- be based on. NETCORE development blog project starblog - (12) razor page dynamic compilation
- Insert sort
- Wechat applet uploading seven cattle cloud laravel
猜你喜欢

System vulnerability exploitation and right raising

AI writes its own code to let agents evolve! The big model of openai has the flavor of "human thought"
![[Niu Ke's questions -sql big factory interview questions] no1 An audio short video](/img/88/b9d5a6d6196f72cf6808d610e3b8fd.png)
[Niu Ke's questions -sql big factory interview questions] no1 An audio short video

How does twitter decentralize? Look at these ten socialfi projects

TCL华星发布全球首款0.016Hz超低频OLED穿戴设备屏

Convenient and easy to master, vivo intelligent remote control function realizes the control of household appliances in the whole house

CentOS uses composer install to report an error - phpunitphppunit 8

How to implement dart asynchrony

Clue binary tree

Flyter color gradient and follow button imitating Taobao gradient
随机推荐
【BP回归预测】基于matlab GA优化BP回归预测(含优化前的对比)【含Matlab源码 1901期】
Beifu twincat3 third-party servo motor -- Taking Huichuan is620n servo as an example
首個女性向3A手遊要來了?獲IGN認可,《以閃亮之名》能否突出重圍
processes 不够用了 ,用户登陆不了
TCL华星发布全球首款0.016Hz超低频OLED穿戴设备屏
System vulnerability exploitation and right raising
Insert sort
Low power radar sensing module, application of smart lock radar sensing scheme, smart radar sensor technology
Fatal NI connect error 12170.报错处理
插入排序
"Defi moral paradox" behind solend farce
Dart异步是怎麼實現
Basic operation of sequence table
How to quickly locate bugs and write test cases?
二叉树线索化
How does twitter decentralize? Look at these ten socialfi projects
LOCAL=NO
[leetcode] 17 backtracking (letter combination of telephone number)
It is about one-step creating Yum source cache in Linux
SSM inpatient management system