go语言学习

参考博客

1、go语言的基本组成

  • 包声明:非注释的第一行指明,如package main
  • 引入包:import “fmt”,引入fmt包
  • 函数:每一个可执行程序必须拥有一个main函数
  • 变量
  • 语句/表达式:一行代表一个语句结束
  • 注释

go版本的hello world

package main
import "fmt"
func main(){
	//终端输出hello world
	fmt.Println("Hello world!")
}

当标识符以一个大写字母开头,可被外部包的代码所用(导出);当标识符以小写字母开头,则对包外是不可见的。

2、数据类型

  • 布尔型
  • 数字类型
  • 字符串类型
  • 派生类型:指针类型、数组类型、结构化类型、Channel类型、函数类型、切片类型、接口类型、Map类型

2.1 变量

声明变量使用var关键字,格式:var identifier typename.

package main
import "fmt"
func main(){
	var a int=27
	fmt.Println(a)
}

  • 若变量没有初始值,默认为零值。
  • 若变量没有指定类型,通过变量的初始值来判断变量类型。
  • :=符号,声明语句,不可以定义一个变量后使用该符号初始化变量
  • 多变量声明,可同时声明多个类型相同的变量(非全局变量)
  • 全局变量声明 var(vname1 v_type1 vname2 v_type2)
  • 匿名变量_(空白标识符),任何赋给这个标识符的值都将被抛弃
  • 变量作用域:局部、全局
package main
import "fmt"
func GetData()(int,int){
	return 10,20
}
func main(){
	//变量没有指定类型
	var d=true
	fmt.Println(d)
	//多变量声明
	var x,y int
	var c,d int=1,2
	g,h:=123,"hello"//:=符号的使用
	//全局变量
	var(
		a int
		b int
	)
	//匿名变量
	a,_:=GetData()
	_,b:=GetData()
	fmt.Println(a,b)
}

2.2 指针

  • 指针声明及初始化
var ip *int/*声明指针变量*/
var fp *float32

var a int=20
ip=&a/*指针初始化*/
  • 空指针:nil

2.3 数组

1、声明数组:需指定元素类型及元素个数

//var variable_name [SIZE] variable_type
var balance [10] float32

2、初始化数组

//1、直接初始化
var balance=[5]float32{1000.0,2.0,3.4,7.0,50.0}
//2、通过字面量在声明数组的同时快速初始化数组
balance2:=[5]float32{1000.0,2.0,3.4,7.0,50.0}
//3、数组长度不确定,编译器通过元素个数自行推断数组长度,[]中填入...
var balance3=[...]float32{1000.0,2.0,3.4,7.0,50.0}
//4、长度确定,指定下标进行部分初始化
balance4:=[5]float321:2.03:7.0

3、go中数组名含义:仅代表整个数组,不同于c语言中数组名本质上是数组中第一个元素的地址
4、数组指针
防止数组作为参数传递的时候浪费空间,还可以利用数组指针和for range来遍历数组

var a=[...]int{1,2,3}//a是一个数组
var b=&a //b是指向数组的指针
for i,v:=range b{//通过数组指针迭代数组的元素
	fmt.Println(i,v)
}

2.4 结构体

结构体中定义多个不同的数据类型
1、声明结构体及结构体变量

//1、声明结构体 type struct
type struct_variable_type struct{
	member definition
	member definition
	...
	member definition
}
//2、声明结构体变量
variable_name:=struct_variable_type{value1,value2...valuen}
variable_name:=struct_variable_type{key1:value1,key2:value2...keyn:valuen}

2、访问结构体成员
结构体变量名.成员名

package main
import "fmt"

type Books struct{
	title string
	author string
}

func main(){
	var book1 Books
	book1.title="Go 语言入门"
	book1.author="mars.hao"
}

3、结构体指针

//1、定义结构体指针
var struct_pointer *Books
//2、结构体指针初始化
struct_pointer=&book1
//3、使用结构体指针访问结构体成员,使用.操作符
struct_pointer.title

2.5 字符串

1、字符串底层结构在reflect.StringHeader中定义

type StringHeader struct{
	Data uintptr//字符串指向的底层字节数组
	Len int//字符串的字节的长度
}

2、字符串UTF8编码
3、字符串的强制类型转换:[]byte []rune

2.6 slice

1、slice底层结构在reflect.SliceHeader中定义(简化版的动态数组)

type SliceHeader struct{
	Data uintptr//指向底层的数组指针
	Len int//切片长度
	Cap int //		切片最大长度
}

切片的类型和长度信息无关,只要是相同类型元素构成的切片均对应相同的切片类型
2、append():内置的范型函数,可以向切片中增加元素

//1、在切片尾部追加n个元素
//尾部添加在容量不足的条件下需要重新分配内存,即使容量足够,依然需要用append函数的返回值来更新切片本身
var a []int
a=append(a,1)//追加1个元素
a=append(a,1,2,3)//追加多个元素,手写解包方式
a=append(a,[]int{1,2,3}...)//追加一个切片,切片需要解包

//2、在切片开头位置添加元素
//在开头一般都会导致内存的重新分配,而且会导致已有的元素全部复制1次,比从尾部追加元素的性能差很多
var a = []int{1,2,3}
a = append([]int{0}, a...)        // 在开头位置添加1个元素
a = append([]int{-3,-2,-1}, a...) // 在开头添加1个切片

//3、append链式操作
//每个添加操作中的第二个append调用都会创建一个临时切片,并将c[i:]的内容复制到新创建的切片中,然后将临时创建的切片再追加到c[:i]
var c []int
c = append(c[:i], append([]int{x}, c[i:]...)...)     // 在第i个位置插入x
c = append(c[:i], append([]int{1,2,3}, c[i:]...)...) // 在第i个位置插入切片

//4、append和copy组合
a= append(a, 0)     // 切片扩展1个空间
copy(a[i+1:], a[i:]) // a[i:]向后移动1个位置
a[i] = x             // 设置新添加的元素


3、删除元素

//1、从开头位置删除
//直接移动数据指针
a = []int{1, 2, 3, ...}
a = a[1:]                       // 删除开头1个元素
a = a[N:]                       // 删除开头N个元素
//将后面的数据向开头移动,使用append原地完成,不会导致内存空间结构的变化
a = append(a[:0], a[1:]...) // 删除开头1个元素
a = append(a[:0], a[N:]...) // 删除开头N个元素
//使用copy将后续数据向前移动
a = a[:copy(a, a[1:])] // 删除开头1个元素
a = a[:copy(a, a[N:])] // 删除开头N个元素

//2、从中间位置删除,需要对剩余的元素进行一次整体挪动
//append删除操作
a = append(a[:i], a[i+1], ...)
a = append(a[:i], a[i+N:], ...)
//copy删除操作
a = a[:copy(a[:i], a[i+1:])] // 删除中间1个元素
a = a[:copy(a[:i], a[i+N:])] // 删除中间N个元素

//3、从尾部删除,删除切片尾部的元素是最快的
a = a[:len(a)-1]   // 删除尾部1个元素
a = a[:len(a)-N]   // 删除尾部N个元素

2.7 函数

1、具名函数:具有函数名、返回值以及函数参数的函数

func Add(a, b int) int {
    return a+b
}

2、匿名函数:指不需要定义函数名的一种函数实现方式,它由一个不带函数名的函数声明和函数体组成。

var Add = func(a, b int) int {
    return a+b
}

3、函数声明与定义

func fuction_name([parameter list])[return types]{
	函数体
}

4、函数传参

  • 函数可以有多个参数和多个返回值,还支持可变数量的参数,可变数量的参数必须是最后出现的参数,可变数量的参数其实是一个切片类型的参数。
  • 当可变参数是一个空接口类型时,调用者是否解包可变参数会导致不同的结果。
func main(){
	var a = []int{1, 2, 3}
	Print(a...)   // 解包,相当于直接调用Print(1,2,3)
	Print(a)	  // 未解包,相当于直接调用Print([]int{}{1,2,3})
}

func Print(a ...int{}) {
	fmt.Println(a...)
}

你可能感兴趣的:(golang)