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类型
记录真或者假

②:数值类型

  • int8int16int32int64int
  • uint8uint16uint32uint64uint
  • 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 271 其他的一次类推了,其中前缀加了u的表示无符号型,即没有负数,直接从0 2 x − 1 2^x-1 2x1 即可

③: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 3string类型的切片。

// 声明一个空切片
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

https://oktools.net/json2go

我们处理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语法知识笔记的主要内容,如果未能解决你的问题,请参考以下文章

Golang学习笔记

go学习Golang底层学习笔记

go学习Golang底层学习笔记

Go语言 语法详解笔记(上)

Golang入门:一天学完GO的基本语法

golang 小知识-持续更新中