Go语言入门教程(省略与C相同的部分语言规则)

教程网址:https://www.runoob.com/go/go-tutorial.html

Go 语言语法与 C 相近,有C的基础的话入门很简单。下面的笔记直接去掉了跟C语言重叠的部分规则。

Go语言教程

第一个 Go 程序 hello.go(Go 语言源文件的扩展是 .go),代码如下:

package main
import "fmt"

func main() {  
    fmt.Println("Hello, World!")
}

注意 { 不能单独放一行

运行go程序的命令

go run hello.go 

也可以先build后运行

go bulid hello.go  #编译生成二进制文件hello
./hello   #运行二进制文件

Go 语言结构

  1. package main 定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。
  2. import "fmt" 引入fmt 包,fmt 包实现了格式化 IO(输入/输出)的函数。
  3. func main() 是程序开始执行的函数。每一个可执行程序所必须包含main 函数,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)。
  4. 注释方式跟C/C++相同,用 // 或 /*… */
  5. fmt.Println(…) 输出字符串,并在最后自动增加换行字符 \n,等同于fmt.Print(“hello, world\n”)
  6. 以一个大写字母开头的标识符(包括常量、变量、类型、函数名、结构字段等等)对象,如:Group1可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,只能在包内使用(像面向对象语言中的 protected )。

Go 语言基础语法

与C/C++基本相同,建议多用空格使语句更美观。

Go 语言数据类型

与C/C++一样,在 Go 编程语言中,数据类型用于声明函数和变量。数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。

布尔型bool、整型 int 和浮点型 float32、float64 等等。

Go 语言变量

  1. 声明变量时指定变量类型

    var identifier type   //声明一个type类型的变量identifier
    identifier = value    //给变量赋值
    var a string = "Runoob"
    
    var identifier1, identifier2 type	//声明两个type类型的变量identifier1、identifier2
    var b, c int = 1, 2
    
  2. 声明变量时不给定变量类型,让编译器根据值自行判定变量类型

    var v_name = value
    var b = true
    
  3. 极致偷懒:声明变量时不仅不给定变量类型,还把var省略掉

    v_name := value
    a := 1   //注意使用:=时左边必须声明新的变量,不能用来给已声明的变量赋值
    s := "fight"
    

    看起来的话使用这种方法最简洁,但是它只能用在函数体中,用来声明局部变量,不能用来声明全局变量。声明全局变量还是得用前面两种。

声明了一个局部变量却没有在相同的代码块中使用它,会得到编译错误。而全局变量是允许声明但不使用。

go语言允许并行赋值,也就是类似 var b , c = 1 , true ,因此go函数可以返回多个返回值(像python一样)。

Go 语言常量

常量是指不会被改变的量。

const b string = "abc"  //显式类型定义
const b = "abc"		//隐式类型定义
const (   //枚举
    Unknown = 0
    Female = 1
    Male = 2
)

iota,特殊常量,可以认为是一个可以被编译器修改的常量。iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

Go 语言运算符&条件语句

跟C/C++一模一样

Go 语言循环语句

for循环有三种形式:

for init; condition; post { }
for condition { }  //跟while一样
for { }  //无限循环

举实例代码是最简洁明了的。

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:

for key, value := range oldMap {
    newMap[key] = value
}

计算1~10的数字之和

package main

import "fmt"

func main() {
        sum := 0
        for i := 0; i <= 10; i++ {
                sum += i
        }
        fmt.Println(sum)
}

For-each range 循环

这种格式的循环可以对字符串、数组、切片等进行迭代输出元素。

package main
import "fmt"

func main() {
        strings := []string{"google", "runoob"}
        for i, s := range strings {
                fmt.Println(i, s)
        }


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

Go 语言函数

Go 语言函数定义格式如下:

func function_name( [parameter list] ) [return_types] {
   函数体
}

实例

/* 函数返回两个数的最大值 */
func max(num1, num2 int) int { //传参时不用写var
   /* 声明局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result
}

上述的是值传递,下面的是引用传递

/* 定义交换值函数*/
func swap(x *int, y *int) {
   var temp int
   temp = *x    /* 保持 x 地址上的值 */
   *x = *y      /* 将 y 值赋给 x */
   *y = temp    /* 将 temp 值赋给 y */
}

Go 语言变量作用域

跟C/C++一模一样

Go 语言数组

Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:

var variable_name [SIZE] variable_type

以上为一维数组的定义方式。例如以下定义了数组 balance 长度为 10 类型为 float32:

var balance [10] float32	//[]中必须填数字

数组初始化:

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} //初始化[]中可以不填数字,让编译器自行判断

访问数组元素

var salary float32 = balance[3]

向函数传递数组

func getAverage(arr []int, size int) float32
{
   var i int
   var avg, sum float32  
   for i = 0; i < size; ++i {
      sum += arr[i]
   }
   avg = sum / size
   return avg;
}

Go 语言指针

一个指针变量指向了一个值的内存地址。

以下是有效的指针声明(都是空指针 nil ):

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮点型 */

指针使用流程:

  • 定义指针变量。
  • 为指针变量赋值。
  • 访问指针变量中指向地址的值。
package main

import "fmt"

func main() {
   var a int= 20   /* 声明实际变量 */
   var ip *int        /* 声明指针变量 */

   ip = &a  /* 指针变量的存储地址 */

   fmt.Printf("a 变量的地址是: %x\n", &a  )
   fmt.Printf("ip 变量储存的指针地址: %x\n", ip )	/* 指针变量的存储地址 */
   fmt.Printf("*ip 变量的值: %d\n", *ip )	 /* 使用指针访问值 */
}

Go 语言结构体

直接上实例

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
    var Book1 Books        /* 声明 Book1 为 Books 类型 */
    /* book 1 描述 */
    Book1.title = "Go 语言"
    Book1.author = "www.runoob.com"
    Book1.subject = "Go 语言教程"
    Book1.book_id = 6495407
    
    // 创建一个新的结构体
    var Book2 Books = Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407}
    // 也可以使用 key => value 格式 , 忽略的字段为 0 或 空
   	var Book3 Books = Books{title: "Go 语言", author: "www.runoob.com"} 
}

访问结构体成员也是跟C/C++一样

结构体.成员名"

你可以定义指向结构体的指针类似于其他指针变量,格式如下:

var book_pointer *Books

以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前:

book_pointer = &Book1

使用结构体指针访问结构体成员,使用 “.” 操作符:

book_pointer.title

那这跟Book1.title好像一样啊,似乎是没什么意义。

Go 语言切片(Slice)

与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

你可以声明一个未指定大小的数组来定义切片:

var identifier []type

或使用make()函数来创建切片:

var slice1 []type = make([]type, len)  //len是切片的初始长度
slice1 := make([]type, len) //简写版本

切片初始化

s :=[] int {1,2,3 } //[]表示是切片类型,{1,2,3}初始化值依次是1,2,3.其cap=len=3
s := arr[startIndex:endIndex] //将数组arr中从下标startIndex到endIndex-1 的元素创建为一个新的切片

len() 方法获取切片长度:len(s)

截取部分切片,类似python,比如 s[1:3] 代表第二个元素到第三个元素(注意包括索引下限的元素,不包括索引上限的元素)。

拷贝切片的 copy 方法和向切片追加新元素的 append 方法

package main

import "fmt"

func main() {
   var numbers []int
   numbers = append(numbers, 1)   /* 向切片添加一个元素 */
   /* 创建切片 numbers1 是之前切片的两倍容量*/
   numbers1 := make([]int, len(numbers), (cap(numbers))*2)
   copy(numbers1,numbers)/* 拷贝 numbers 的内容到 numbers1 */
}

Go 语言范围(Range)

Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。

package main
import "fmt"
func main() {
    //这是我们使用range去求一个slice的和。使用数组跟这个很类似
    nums := []int{2, 3, 4}
    sum := 0
    for _, num := range nums {
        sum += num
    }
    //在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。

    //range也可以用在map的键值对上。
    kvs := map[string]string{"a": "apple", "b": "banana"}
    for k, v := range kvs {
        fmt.Printf("%s -> %s\n", k, v)
    }
    //range也可以用来枚举Unicode字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
    for i, c := range "go" {
        fmt.Println(i, c)
    }
}

Go 语言Map(集合)

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,可以像迭代数组和切片那样迭代它。不过Map 是无序的,无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

定义map

/* 声明变量,默认 map 是 nil ,没有初始化,不能用来存放键值对*/
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数初始化map */
map_variable := make(map[key_data_type]value_data_type)

如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对

package main

import "fmt"

func main() {
    countryCapitalMap := make(map[string]string)/*创建集合 */

    /* map插入key - value对,各个国家对应的首都 */
    countryCapitalMap [ "France" ] = "巴黎"
    countryCapitalMap [ "Italy" ] = "罗马"

    /*使用键输出地图值 */
    for country := range countryCapitalMap {
        fmt.Println(country, "首都是", countryCapitalMap [country])
    }

    /*查看元素在集合中是否存在 */
    capital, ok := countryCapitalMap [ "American" ]
    if (ok) {
        fmt.Println("American 的首都是", capital)
    } else {
        fmt.Println("American 的首都不存在")
    }
}

Go 语言递归函数

十分简单,与C/C++相同

Go 语言类型转换

十分简单,也跟C/C++一样

var num_int int = 5
var num_float32 float32
num_float32=float32(num_int)

剩余部分省略

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章