1. Golang基础知识

本文介绍了Go语言的基本特性和语法,包括变量、数据类型、控制结构等内容。重点讲解了Go语言的特性,如支持运行时动态类型、强类型、类型安全等,并通过示例展示了如何编写Go程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.1.1 Go语言的诞生背景

1.1.2 语言特性

1.1.3 Go语言的特性

静态语言,支持运行时动态类型、强类型、支持隐式推导、类型安全、支持type自定义、类型组合支持面向对象、

接口Duck模型、通过接口支持多态、不支持泛型、发射支持、支持垃圾回收、支持协程、支持交叉编译、跨平台

1.2 初识Go程序

hello.go

package main

import "fmt"

func main() {

    fmt.Printf("Hello , world\n")

}

go源代码默认UTF-8

区分大小写

{ 不能单独起一行

编译运行

go build hello.go

1.3 Go词法单元

sum := a+b

1.3.1 token

1.3.2 标识符

go变量必须是以字母或者下划线开头。

1.3.3 操作符和分隔符

1.3.4 字面常量

1.4 变量和常量

1.4.1 变量

1.显式的完整声明

var varName dataType [= value]  Go的变量声明后会立刻为其分配空间

var a int = 1

var a int = 2*3

var a int = b

2. 短类型声明

varName := value 只能出现在函数内 , 此时Go编译器自动进行数据类型推断。

Go支持多个类型变量同时声明并且赋值,例如:  a, b := 1, "hello"

1.4.2 常量

//类似枚举的iota

const (

    c0 = iota // c0 == 0

    c1 = iota // c1 == 1

    c2 = iota // c2 == 2

)

// 简写模式

const (

    c0 = iota // c0 == 0

    c1           // c1 == 1

    c2          // c2 == 2

)

1.5 基本数据类型

Go是一种强类型的静态编译语言

1.5.1 布尔类型

var ok bool

ok = true  或者 ok := false

布尔型数据和整形数据不能进行相互转换

var a bool

a = 1 // error

1.5.2 整形

var a int = (1 + 2) * 3

var b int = 1000 >> 2

1.5.3 浮点型  (float32 和 float64)

var b := 10.00 计算机很难进行浮点数的精确表示和存储,因此两个浮点数之间不应该使用 == 或者 != 进行比较,高精度科学计算应该使用 math 标准库

1.5.4 复数类型

var value1 complex64 = 3.1 +5i

value2 := 3.1 + 6i

Go有三个内置函数处理复数

var v = complex(2.1, 3) // 构造一个复数

a := real(v) // 返回复数实部

b := image(v) // 返回复数虚部

1.5.5 字符串

1.   var a = "hello world"  字符串是常量,可以通过类似数组的索引访问其字节单元,但不能修改某个字节的值,例如:

var a = "hello , world"

b := a[0]

a[1] = 'a' // error

2.  字符串转换为切片 []byte(s)要慎重,尤其是当数据量比较大时(每转换一次都需要复制内容)

3. 字符串尾部不包含NULL字符,这一点和C/C++不一样

4.字符串类型底层实现是一个二元的数据结构,一个是指针指向字节数组的起点,另一个是长度,例如:

// runtime/string.go

209  type stringStruce struce {

210        str unsafe.Pointer       // 指向底层字节数组的指针

211         len int                        // 字节数组长度

212   }

1.5.6 rune类型

Go内置两种字符类型:一种是byte,也是uint的别名、另一种表示Unicode编码字符的rune,rune在Go内部是int32类型的别名,占4个字节。

Go默认的字符编码是UTF-8,如果需要转换编特殊的编码,则使用Unicode/UTF-8标准包。

1.6 复合数据类型

Go的复合类型有:指针、数组、切片、字典(map)、通道、结构和接口

1.6.1 指针

1.

var a = 11

p := &a

2.Go不支持指针的运算。

a := 1234

p := &a

p++ // 报错

3. 函数中允许返回全局变量的地址

func sum(a, b int) *int {

    sum := a + b

    return &sum  // 允许,sum会分配在heap上

}

1.6.2 数组

var arr [2]int   // 声明一个有两个整型的数组,但元素默认值都是0,一般很少这样使用

array := [...]float64 { 7.0, 8.5, 9.1 } // [...]后面跟字面量初始化列表

数组初始化

a := [3]int {1, 2, 3} //指定长度和初始化字面量

a := [...]int {1, 2, 3} //不指定长度,但是由后面的初始化列表数量来确定其长度

a := [3]int {1:1, 2:3} //指定总长度,并通过索引值进行初始化,没有初始化元素时使用类型默认值

a :=[...]int {1:1, 2:3} //不指定总长度,通过索引值进行初始化,数组长度由最后一个索引值确定,没有指定索引的元素被初始化为类型的零值。

数组的特点

1、数组创建完长度就固定了,不可以再追加元素

2、数组是值类型,数组赋值或者作为函数参数都是值拷贝。

3、数组长度是数组类型的组成部分, [10]int 和 [20]int 表示不同类型

4、可以根本数组创建切片。

数组相关操作

1、数组元素访问

a := [...]int {1, 2, 3}

b := a[0]

for i, v := range a {

}

2、数组长度

a := [...]int {1, 2, 3}

alength:= len(a)

for i:=0; i< alength; i++ {

}

1.6.3 切片

Go切片 slice 是一种变长数组,其数据结构中有指向数组的指针,是一种引用类型

// src/runtime/slice.go

11 type slice struct {

12 array unsafe.Pointer

13 len int

14 cap int

}

Go切片维护三个元素:指向底层数组的指针、切片元素数量、底层数组容量。

1、切片的创建,创建语法 array[b:e]

var array = [...]int {0, 1, 2, 3, 4, 5, 6} // 创建有76个int型元素的数组

s1 := array[0:4] // [0 1 2 3]

s2 := array[:4] // [0 1 2 3]

s3 := array[2:] // [2 3 4 5 6]

通过内置函数 make 创建切片 (注意:由make创建的切片各元素被默认值初始化为切片元素类型的零值),例如:

a := make([]int, 10)           // len = 10, cap = 10   [0 0 0 0 0 0 0 0 0 0]

b := make([]int, 10, 15)    // len=10, cap=15        [0 0 0 0 0 0 0 0 0 0]

直接声明切片类型变量是没有意义的,例如:

var a []int

fmt.Printf("%v\n", a) // 结果为 []

2 切片支持的操作

len()

cap() 返回切片底层数据容量

append() 对切片追加元素

copy() 用于复制一个切片

例如:

a := [...]int {0, 1, 2, 3, 4, 5, 6}

b := make([]int, 2, 4)  //  len(b)  = 2 , cap(b) = 4

b = append(b, 1)       // len(b)=3   [0 0 1]  cap(b) 4

c := a[0:3]          

b = append(b, c...)    //   [0 0 1 0 1 2]      len(b) = 6   cap(b)=8//底层数组发生扩展

d := make([]int, 2, 2)

copy(d, c) // copy只会复制d和c中长度最小的      [0, 1]    len(d)=2 cap(d)=2

3 字符串和切片相互转换

str := "hello, 世界"   //通过字符串字面量初始化一个字符串str

a := []byte(str)         //将字符串转换为[]byte类型切片

b := []rune(str)         //将字符串转换为[]rune类型切片

1.6.4 map

Go语言内置的字典类型叫做map , 格式为: map[K]T , map也是一种引用类型

1.创建map

使用字面量创建

ma := map[string]int {"a":, "b":2}

fmt.Println(ma["a"])

fmt.Println(ma["b"])

使用内置的make函数创建,例如:

make(map[K]T) // map的容量使用默认值   

mp1 := make(map[int]string)

mp1[1] = "tom"

make(ma[K]T, len) // map的容量使用给定的len值   

mp2 := make(map[int]string, 10)

mp2[1] = "pony"

2. map支持的操作

可以使用range遍历一个map类型变量 ,但是不保证每次迭代元素的顺序。

可以用len()函数返回map中键值对数量,例如:

mp := make(map[int]string)

mp[1] ="tom"

mp[1] = "pony"

mp[2] = "jaky"

mp[3] = "andes"

删除map中的某个键值,delete(mapName, key)

delete(mp, 3)

for k, v := range mp {

}

注意:

Go内置的map不是并发安全的,并发安全的map可以使用标准包sync中的map

不要直接修改map value内某个元素的值,如果想修改map的某个键值,则必须整体赋值

type User struce {

    name string

    age int

}

ma := make(map[int]User)

andes := User {

    name: "andes",

    age: 18,

}

ma[1] = andes

ma[1].age = 19 //报错,不能通过map引用直接修改

andes.age =19

ma[1] = andes //必须整体替换value

1.6.5 struct

Go中的struct类型和C类似,由多个不同类型元素组合而成。

这里有两层含义:1、struct结构中的类型可以是任意类型。2、struct的存储空间是连续的,其字段按照声明时的顺序存放(注意字段之间有对齐要求)

struct有两种形式:一种是struct类型字面量,另一种是使用type声明的自定义struct类型

1、struct类型字面量

struct {

    FeildName FeildType

    FeildName FeildType

    FeildName  FeildType

}

2、自定义struct类型

type TypeName strict {

    FeildName FeildType

    FeildName FeildType

    FeildName FeildType

}

3、struct类型变量的初始化

type Person struct {

    Name string

    Age int

}

type Student struct {

    *Person

    Number int

}

//按照类型声明顺序,逐个赋值

a := Person { “Tome”, 21} //不推荐这种初始化方式,一旦struct增加字段,则整个初始化语句都会报错

推荐这种使用Feild名字的初始化方式,没有指定的字段则默认初始化为类型的零值

p := &Person {

    Name: "tata",

    Age: 12,

}

s := Student {

    Person: p,

    Number: 110,

}

1.7 控制结构

1.7.1 语句

if后面的条件判断子句不需要用小括号括起来

{必须放在行尾,和if或者if else放在一行

if 后面可以带一个简单的初始化语句,并以分好分割,该简单语句声明的变量作用域是整个if语句块,包括后面的else if 和 else 分支

Go语言没有条件运算符 ( a > b ? a : b), 这也符合Go的设计哲学,只提供一种方法做事情。

if 分支语句遇到return后直接返回,遇到break则跳过break下方的if语句块

简单示例:

if  x <= y {

    return y

} else {

    return x

}

一个完整的 if else 语句示例:

if x := f();  x < y { //初始化语句中的声明变量x

    return x

} else if x > z { //x在else if 里一样可以被访问

    return z

} else {

    return y

}

err, file := os.Open("xxxx")

if err != nil {

    retutrn nil, err

}

defer file.Close()

1.7.2 switch 语句

switch和if语句一样,switch后面可以带一个简单的初始化语句

通fallthough语句来强制执行下一个case字句(不再判断下一个case子句的条件)

switch i:= "y";i {

case "y", "Y": //多个case值使用逗号分隔

    fallthrough

case "n", "N"

}

1.7.3 for语句

for init; condition; post {

}

for可以对数组、切片、字符串、map和通道的访问,例如:

//访问map

for key, value := range map {}

for key := range map {}

//访问数组

for index, value := range array {}

for index := range array{}

for _, value := range array{}

//访问切片

for index, value := range silce {}

for index := range slice{}

for _, value := range slice{}

//访问通道

for value := range channel {}

1.7.4 标签和跳转

goto 、 break、 continue

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值