Go语法知识笔记
Posted MangataTS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语法知识笔记相关的知识,希望对你有一定的参考价值。
文章目录
前言
记录一些Go的语法糖,当然也可能会跳过一些简单的语法~
一、结构分析
package main
import (
"fmt"
)
func Hello(str string)
fmt.Println("Hello " + str)
func main()
Hello("World!")
这是一个简单的Go
代码,我们可以看到
- 第一行
package main
代表这个文件属于main包的一部分,main
包也就是程序的入口包。第一行包主代表这个文件属于主包的一部分,主包也就是程序的入口包。 - 第三行
import
的操作表示的是引入一些标准库的包,可以简单的和C
语言的#include
预处理对应起来 - 第七行这里就是
Go
的一个函数的结构了,我们这里接受一个string
类型的str
变量,然后将其加上Hello
前缀打印输出 - 第十一行这里就是主函数了,类比
C
语言的main
,即程序的启动入口
二、变量&常量
变量的基本类型:
①:bool类型
记录真或者假
②:数值类型
int8
、int16
、int32
、int64
、int
uint8
、uint16
、uint32
、uint64
、uint
float32
,float64
complex64
,complex128
byte
rune
记录数值
我们发现有一些变量后面跟了个数字,这其实就是表示这个变量的占用的位的大小,例如
int8
就表示占用8
个bit,能表示的数字个数就是 2 8 2^8 28 考虑到 0 0 0 和负数的情况,那么这个int8
表示的范围就是: − 2 7 -2^7 −27 ~ 2 7 − 1 2^7-1 27−1 其他的一次类推了,其中前缀加了u
的表示无符号型,即没有负数,直接从0
到 2 x − 1 2^x-1 2x−1 即可
③:string类型
用于记录字符串类型的值
变量的定义
①:第一种通过var
关键字来定义
var a = "hello"
var b = 3
var c float64 = 3.14
注意这里如果不给变量初始化的话,则需要带上这个变量的类型:
var a string
var b int
var c float64
②:直接定义
a := "hello"
b := 3
c := 3.14
当然变量定义的时候可以使用强转
常量的定义
常量的定义其实就是将变量的var
变成const
关键字即可
const str = "Hello World!"
三、分支&循环
if-else
package main
import (
"fmt"
)
func main()
var a int
fmt.Scanf("%d", &a)
if a < 10
fmt.Println("step1")
else if a < 20
fmt.Println("step2")
else
fmt.Println("step3")
这里我们发现和C/C++
的区别在于判断条件没有括号包裹了,如果非要加括号,Go
也是能运行的
switch case
package main
import (
"fmt"
)
func main()
var a int
fmt.Scanf("%d", &a)
switch a
case 1:
fmt.Println("This is 1")
case 2:
fmt.Println("This is 2")
case 3:
fmt.Println("This is 3")
default:
fmt.Println("This is error")
- 在
c++
里面,switch case
如果不在目标case
下加break
的话会然后会继续往下跑完所有的case
,在go
语言 里面的话是不需要加break
的。- 相比
C
或者C++
,go
语言里面的switch
功能更强大。可以使用任意的变量类型,甚至可以用来取代任意的if else
语句。你可以在switch
后面不加任何的变量,然后在case
里面写条件分支。这样代码相比你用多个if else
代码逻辑会更为清晰
for循环
Go
只有一个for
循环,不过也已经够了
package main
import (
"fmt"
)
func main()
var a int
fmt.Scanf("%d", &a)
for i := 1; i < a; i++
fmt.Println("index = ", i)
while类型的写法:
package main
import (
"fmt"
)
func main()
var a int
fmt.Scanf("%d", &a)
var i int = 1
for i <= a
fmt.Println("index = ", i)
i++
for-range
for key, value := range oldMap
newMap[key] = value
注意这里的key
有的时候不会用上,所以可以用_
下划线代替,这样就不会报没使用这个变量的错了
四、数组
数组的定义只需要将申请的空间放在变量名和类型中间即可
eg:
//声明数组
var a[10]int
//声明并初始化操作
var d = [3]int1,2,3
二维数组类似:
var a[5][5]int
var d = [5][5]int1,2,3,4,5
数组长度我们可以通过len
函数获取,例如
//声明数组
var a[10]int
//声明并初始化操作
var d = [3]int1,2,3
//输出长度
fmt.Println(len(d))
元素访问就是正常下标访问即可,例如:a[i][j]
五、函数
标准格式:
func function_name( [parameter list] ) [return_types]
函数体
结构记录:
// 传入两个 int 类型的值,然后返回其和,且也是int类型
func add(a int, b int) int
return a + b
// 传入一个stirng参数,然后没有返回值
func printt(str string)
fmt.Println("Hello", str)
Go
函数可以返回多个值,一般来说,第一个是函数的返回值,第二个是错误信息。
func exists(m map[string]string, k string) (v string, ok bool)
v, ok = m[k]
return v, ok
返回错误的情况:
func (c *Client) Do(req *Request) (*Response, error)
return c.do(req)
我们调用这个函数的时候就需要给出两个变量用于接受这个返回值:
resp, err := client.Do(req)
六、切片
切片(slice
)与数组的区别是切片的长度不是固定的而是可变的,比数组的用途更加广泛。
切片声明需要通过 make
来进行,需要指定切片的类型以及长度,例如下面为创建一个长度为
3
3
3 的string
类型的切片。
// 声明一个空切片
s1 := make([]string, 3)
// 声明并初始化
s2 :=[] int 1,2,3,4,5,6
切片除了长度还有一个容量(capacity
)的概念,可以在声明切片的时候同时指定长度和容量。
s := make([]string, 3, 10)
通过s1 := s[startIndex:endIndex]
可以创造新切片s1
,且s
可以为数组,其余操作貌似和python
的切片类似,不过go
的切片更像一个变长数组或者说链表,go
支持append
函数用于向切片中追加值,支持copy
函数用于复制切片
package main
import "fmt"
func main()
var numbers []int
printSlice(numbers)
/* 允许追加空切片 */
numbers = append(numbers, 0)
printSlice(numbers)
/* 向切片添加一个元素 */
numbers = append(numbers, 1)
printSlice(numbers)
/* 同时添加多个元素 */
numbers = append(numbers, 2,3,4)
printSlice(numbers)
/* 创建切片 numbers1 是之前切片的两倍容量*/
numbers1 := make([]int, len(numbers), (cap(numbers))*2)
/* 拷贝 numbers 的内容到 numbers1 */
copy(numbers1,numbers)
printSlice(numbers1)
func printSlice(x []int)
fmt.Printf("len=%d cap=%d slice=%v\\n",len(x),cap(x),x)
七、 指针
貌似和C/C++
中的指针的操作是一样的,通过*
访问,然后&
是取地址符
不过Go
中的指针不支持指针运算,例如下面的代码就会报错:
main.go:6: invalid operation: p++ (non-numeric type *[3]int)
package main
func main()
b := [...]int109, 110, 111
p := &b
p++
new创建指针
这里mark一下格式:
ptr := new(int)
,其中的int
可以替换成其他数据类型
其他
-
关于指针的解引用是和
C/C++
类似的 -
想函数中传入指针参数的时候,我们在函数的定义时,需要使用
*
来表示接受指针的
感觉Go
有个弱智的语法,先看代码:
package main
import (
"fmt"
)
func find_max(a []int) int
l := len(a)
ans := a[0]
for i := 0; i < l; i++
if a[i] > ans
ans = a[i]
return ans
func main()
var d = [3]int1, 2, 3
fmt.Println(find_max(d))
这也是C/C++
正常的数组传参,不过这里会报错:
cannot use d (variable of type [3]int) as []int value in argument to find_max
意思大概就是a []int
是一个切片,而传入的d
是一个数组,所以会报错,我们需要将第
20
20
20 行的数据改为切片,即:
fmt.Println(find_max(d[:]))
八、结构体
结构体声明语法:
type StructName struct
FieldName type
不同成员之间直接换行写就行,不用,
隔开,如下:
type StructName struct
a int
b float32
c string
d bool
定义结构体变量:
var t1 StructName
t2 := StructName
a: 1,
b: 1.1,
c: "hello",
d: true,
t3 := StructName1, 1.1, "hello", true
成员函数
成员函数写在结构体外面,格式如下:
func (t StructName) func_name(str string) int
return 1
这里我们将当前的这个结构体传入,当然也可以使用结构体指针,这样就能对当前的这个结构体变量的进行一些修改操作
json转结构体
JSON转Golang Struct
我们处理JSON数据的时候,需要将json构造成一个或者多个结构体的嵌套,那么假设我们有如下的JSON数据:
"rc": 0,
"wiki":
"known_in_laguages": 63,
"description":
"source": "tangible and intangible thing, except labor tied services, that satisfies human wants and provides utility",
"target": null
,
"id": "Q28877",
"item":
"source": "good",
"target": "商品"
,
"image_url": "http://www.caiyunapp.com/imgs/link_default_img.png",
"is_subject": "true",
"sitelink": "https://www.caiyunapp.com/read_mode/?id=6354777915466339550246c5"
,
"dictionary":
"prons":
"en-us": "[gʊd]",
"en": "[gud]"
,
"explanations": [
"a.好的;善良的;快乐的;真正的;宽大的;有益的;老练的;幸福的;忠实的;优秀的;完整的;彻底的;丰富的",
"n.利益;好处;善良;好人",
"ad.=well"
],
"synonym": [
"excellent",
"fine",
"nice",
"splendid",
"proper"
],
"antonym": [
"bad",
"wrong",
"evil",
"harmful",
"poor"
],
"wqx_example": [
[
"to the good",
"有利,有好处"
],
[
"good, bad and indifferent",
"好的,坏的和一般的"
],
[
"good innings",
"长寿"
],
[
"good and ...",
"很,颇;完全,彻底"
],
[
"do somebody's heart good",
"对某人的心脏有益,使某人感到愉快"
],
[
"do somebody good",
"对某人有益"
],
[
"be good for",
"对…有效,适合,胜任"
],
[
"be good at",
"在…方面(学得,做得)好;善于"
],
[
"as good as one's word",
"信守诺言,值得信赖"
],
[
"as good as",
"实际上,几乎等于"
],
[
"all well and good",
"也好,还好,很不错"
],
[
"a good",
"相当,足足"
],
[
"He is good at figures . ",
"他善于计算。"
]
],
"entry": "good",
"type": "word",
"related": [],
"source": "wenquxing"
让我们自己写结构体,也许能写但是回很麻烦,这个时候就需要用到上面的工具了JSON
转Go的结构体
转换出来:
type AutoGenerated struct
Rc int `json:"rc"`
Wiki struct
KnownInLaguages int `json:"known_in_laguages"`
Description struct
Source string `json:"source"`
Target interface `json:"target"`
`json:"description"`
ID string `json:"id"`
Item struct
Source string `json:"source"`
Target string `json:"target"`
`json:"item"`
ImageURL string `json:"image_url"`
IsSubject string `json:"is_subject"`
Sitelink string `json:"sitelink"`
`json:"wiki"`
Dictionary struct
Prons struct
EnUs string `json:"en-us"`
En string `json:"en"`
`json:"prons"`
Explanations []string `json:"explanations"`
Synonym []string `json:"synonym"`
Antonym []string `json:"antonym"`
WqxExample [][]string `json:"wqx_example"`
Entry string `json:"entry"`
Type string `json:"type"`
Related []interface `json:"related"`
Source string `json:"source"`
`json:"dictionary"`
九、错误处理
Go
语言通过内置的错误接口提供了非常简单的错误处理机制。
error
类型是一个接口类型,这是它的定义:
type error interface
Error() string
如果是函数内部抛出异常,那么对于当前函数就应该多一个errors
的接收变量,例如下面的代码示例:
type user struct
name string
password string
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")
当我们需要调用该函数的时候,需要如此调用:
us,err = findUser([]user"xie","1234abcd","xie")
十、标准库
Go内置了非常丰富的标准库工具,常用的标准库包括字符串操作、字符串格式化、json处理、时间处理等。
字符串操作
a := "hello"
// 是否包含
fmt.Println(strings.Contains(a, "ll")) // true
// 字符统计
fmt.Println(strings.Count(a以上是关于Go语法知识笔记的主要内容,如果未能解决你的问题,请参考以下文章