参考博客
go版本的hello world
package main
import "fmt"
func main(){
//终端输出hello world
fmt.Println("Hello world!")
}
当标识符以一个大写字母开头,可被外部包的代码所用(导出);当标识符以小写字母开头,则对包外是不可见的。
声明变量使用var关键字,格式:var identifier typename.
package main
import "fmt"
func main(){
var a int=27
fmt.Println(a)
}
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)
}
var ip *int/*声明指针变量*/
var fp *float32
var a int=20
ip=&a/*指针初始化*/
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]float32(1:2.0,3: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)
}
结构体中定义多个不同的数据类型
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
1、字符串底层结构在reflect.StringHeader中定义
type StringHeader struct{
Data uintptr//字符串指向的底层字节数组
Len int//字符串的字节的长度
}
2、字符串UTF8编码
3、字符串的强制类型转换:[]byte []rune
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个元素
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...)
}