青训营X豆包MarsCode 技术训练营第一课 | Go的基本语法学习与练习

44 阅读4分钟

Go的基本介绍

Go 语言是谷歌 2009 年首次推出并在 2012 年正式发布的一种全新的编程语言,

go语言具有以下特点: 1.高性能、高并发 2.语法简单、学习曲线平缓 3.丰富的标准库 4.完善的工具链 5.静态链接 6.快速编译 7.跨平台 8.垃圾回收

相比于C++而言,Go的语法比较简单,执行效率与C++相差很小,而且自带垃圾回收机制,编译器支持多种平台,跨平台开发简单;相比于Java而言,启动速度快,资源占用少,语法简洁,代码可读性强。

此外,Go具有内置goroutines和channels,简化并发编程。Go语言的格式化工具 go fmt 可以自动格式化代码,避免团队的格式不一致冲突。 比如:

  • 大括号:始终在新的一行开始和结束大括号。
  • 函数定义:参数和返回值类型放在参数名后面。
  • 控制结构ifforswitch 等控制结构的条件表达式不需要括号。
  • 函数定义:参数和返回值类型放在参数名后面。
  • 变量声明:使用 var 关键字或简短声明 :=

格式是:

go fmt ./...

图片.png

可以看到,自动帮我们进行格式化了,非常方便。 图片.png

Go的实践例子

package main


import(
	"fmt"
)

func main(){
	fmt.Println("hello world")
}

我们通过询问AI了解这段代码的功能:

图片.png

  • package main:这一行声明了这个文件属于 main 包。在 Go 语言中,每个文件都必须属于一个包,而 main 包是一个特殊的包,它定义了一个可执行的程序。
  • import("fmt"):这一行导入了 fmt 包。fmt 包是 Go 语言标准库中的一个包,它提供了格式化输入和输出的函数,例如 Println 函数。
  • func main() {...}:这是程序的入口点,即 main 函数。当你运行这个程序时,操作系统会调用这个函数。在这个函数中,我们使用 fmt.Println 函数来打印 "hello world" 到控制台。
package main

import (
	"fmt"
	"math"
)

func main() {

	var a = "initial"

	var b, c int = 1, 2

	var d = true

	var e float64

	f := float32(e)

	g := a + "foo"
	fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0
	fmt.Println(g)                // initialapple

	const s string = "constant"
	const h = 500000000
	const i = 3e20 / h
	fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}

这段代码展示了变量怎么定义, go语言有四种主要声明方式:

    var(声明变量), const(声明常量), type(声明类型) ,func(声明函数)。

var 有点像C++的auto关键字,能够自动推导变量的类型,const相当于C++的const auto。如果需要指定特定类型的话,直接在后面加上就行。相比于C++,更简洁易懂,更方便修改变量的类型。

type 关键字用于定义新的数据类型。相当于C++的typedef关键字,不过有一些差别:


//go语言
type Person struct {
Name string 
Age int 
}


//C++语言
typedef struct {
    std::string name;
    int age;
} Person;



go语言变量的声明方式有以下方式:

  • var 变量名 变量类型

  • 变量声明以关键字var开头,变量类型放在变量的后面,行尾无需分号。 举个例子:

    var name string
    var age int
    var isOk bool
  • 批量定义
 var (
        a string
        b int
        c bool
        d float32
    )
  • := 方式声明并初始化变量。注意::= 方式只能用在函数内部。
f := float32(e)
package main

import "fmt"

func main() {

	s := make([]string, 3)
	s[0] = "a"
	s[1] = "b"
	s[2] = "c"
	fmt.Println("get:", s[2])   // c
	fmt.Println("len:", len(s)) // 3

	
}


go的切片很像C++的vector,切片包含三个部分:

  1. 指向底层数组的指针:指向底层数组的起始位置。
  2. 长度(len) :切片中元素的数量。
  3. 容量(cap) :切片可以增长的最大长度,即从切片起始位置到底层数组末尾的元素数量。

slice的初始化:

slice := make([]T, length, capacity)

//capacity必须大于等于length,不然编译器会报错。capacity可以省略,默认等于length。
//也可以用字面量初始化:

t := make([]string, 3, 10)


  • T:元素类型。
  • length:切片的初始长度。
  • capacity:切片的容量(可选)。

也可以只声明不初始化:


var s []int

需要特别注意的是:go语言追加的格式必须是slice = append(slice, 4), append函数的原理如下:

  1. 容量足够:如果切片的容量足以容纳新的元素,append 会在原切片的基础上扩展长度,并返回一个新的切片,这个新的切片与原切片共享同一个底层数组。
  2. 容量不足:如果切片的容量不足以容纳新的元素,append 会分配一个新的底层数组,将原切片中的元素复制到新数组中,然后在新数组的末尾追加新的元素,并返回一个新的切片,这个新的切片指向新分配的底层数组。

append返回值是一个新的切片,如果不将这个新的切片重新赋值给原来的切片变量,那么原来的切片变量仍然会指向旧的切片,而不会包含新追加的元素。

图片.png