基础数据类型
int int8 int16 int32 int64
uint8 uint16 uint32 uint64
float32 float64
bool(true/false)
数据类型的使用
变量定义使用var,常量定义使用 const
// 01先定义变量,在进行赋值
// ctrl + alt + l 快速排版
var name string
name = "123"
fmt.Println("name:",name)
var age int = 10
fmt.Printf("aga=[%d]\n",age)
// 02定义的时候直接赋值
var gender = "man"
fmt.Println(gender)
// 03 定义直接赋值,使用自动推导,这个最常用
address := "北京"
fmt.Println(address)
// 灰色部分表示形参
test(age,address)
// 04 并行赋值
i,j := 10,20
fmt.Println("变化前","i:",i,"j:",j)
// 直接进行转换
i,j = j,i
fmt.Println("变化后","i:",i,"j:",j)
自增语法
C语言: i++,i–,--i,++i
Go语言:只有i++,i–没有–i,++i,而且自增必须单独一行
i :20
i++
//++i //这个是错误的
//fmt.Println("i:",i++) // 这个是错误的,go不允许和其他代码放在一起,必须单独一行
fmt.Println("i:",i)
指针
go语言不需要释放
package main
import "fmt"
// 定义一个函数,返回一个string类型的指针,go语言返回值写在参数
// 列表后面
func testPtr() *string {
city := "深圳"
ptr := &city
fmt.Printf("testPtr ptr 地址 %p\n",&ptr)
// testPtr ptr 地址 0xc000006038
return ptr //从C语言来说这个是空的
}
func main() {
// go语言也有指针
// 结构体成员调用是
// C语言ptr->name
// GO语言 ptr.name
// GO语言在使用指针时,会使用内部的垃圾回收机制
// gc:garbage collector开发人员不需要手动释放
// C语言不允许返回栈上指针,Go可以
// 程序会在编译的时候就确定了变量的分配位置
// 编译的时候,如果发现有必要的画,就将变量分配到堆上
//01
name := "lxy"
ptr := &name
//name: lxy
fmt.Println("name:",name)
//name ptr 0xc000040240
fmt.Println("name ptr",ptr)
// name type string,ptr type *string
fmt.Printf("name type %T,ptr type %T\n",name,ptr)
// 02 使用new关键字定义
name2Ptr := new(string)
*name2Ptr = "chenchen"
// *name2Ptr chenchen
fmt.Println(" *name2Ptr",*name2Ptr)
// name2Ptr type *string
fmt.Printf("name2Ptr type %T\n",name2Ptr)
// 可以返回栈上的指针,编译器在编译程序时,会自动
// 判断这段代码,将变量分配在堆上
res := testPtr()
fmt.Println("res city:",*res) // res city: 深圳
//res 地址 0xc000006030
fmt.Printf("res 地址 %p\n",&res)
// 空指针,在C语言中是NULL C++:nullptr
// Go语言的空指针为nil
res := "hell go"
strPtr := &res
// if不用括号
// 即使有一行代码也必须加括号
if strPtr == nil {
fmt.Println("strPtr is nil")
}else {
fmt.Println(*strPtr)
}
}
GO语言不支持的语法
- 自增–i,++i不支持
- 不支持地址加减
- 不支持三名运算符?:
- 只有false才能代表逻辑假,数字0和nil不能
GO中的string类型
string定义
name := "duke"
// 需要换行使用反引号``
usage := `./a.out <option>
-h help
-a xxxx`
fmt.Println(name,usage)
/*
duke ./a.out <option>
-h help
-a xxxx
*/
字符串的长度
// C++:name.length
// GO: string没有length方法,可以使用自由函数len()进行处理
len_name := len(name)
fmt.Println("len_name :",len_name)
// 不需要加括号
for i:=0; i<len(name);i++{
fmt.Printf("i:%d,v:%c\n",i,name[i])
}
字符串的拼接
m,n:="Hi GO, hello","world"
fp := m + " " +n + "!"
fmt.Println(fp)
// 不能修改
const address = "北京"
fmt.Println(address)
定长数组
定义 定长数组
// c语言: int nums[10 + 1] = {1,2,3,4}
// go语言: nums := [10]int{1,2,3,4}
// var nums =[10]int{1,2,3,4}
nums := [10]int{1,2,3,4,5,6,7,8,9,10}
遍历 传统方式
for i :=0;i<len(nums);i++{
fmt.Printf("nums[%d]=%d \n",i,nums[i])
}
遍历 方式二 for range 最常用
// key是下标,value是值
// 但是改变value的值不会改变nums
for key,value := range nums{
fmt.Println("key:", key," value:",value)
value += 10 //value是个临时变量,然后不断的被重新赋值,修改他不会影响原值
fmt.Println("value:",value,"nums[key]:", nums[key])
/*
key: 0 value: 1
value: 11 nums[key]: 1
*/
}
// 在GO语言中如果想忽略一个值,可以使用_
for key,_ := range nums{
fmt.Println("key:", key)
}
for _,value := range nums{
fmt.Println("value:", value)
}
// 如果两个都忽略,那么就不能使用 :=而应该直接使用=
for _,_ = range nums{
fmt.Println("value:")
}
不定长数组切片slice
package main
import "fmt"
func main() {
// 不定长数组切片slice
// 定义一个不定长数组切片,包含多个地名
// 定长数组的定义
// names := [10]string{"北京","上海","广州"}
// 不定长数组定义
names :=[]string{"北京","上海","广州"}
fmt.Println("最开始names的长度:",len(names)," 容量:",cap(names))
for k,v := range names{
fmt.Println("k:",k," v:",v)
}
/*
k: 0 v: 北京
k: 1 v: 上海
k: 2 v: 广州
*/
// 1.追加数据
names2 := append(names,"海南岛")
for k2,v2 := range names2{
fmt.Println("k:",k2," v:",v2)
}
names = append(names,"海南岛")
fmt.Println(names)
fmt.Println(names2)
// 2.对于一个切片,不仅有长度的概念len,还有一个容量的概念
// cap()
// 打印长度
fmt.Println("第一次追加元素后names的长度:",len(names)," 容量:",cap(names))
names = append(names,"三亚")
fmt.Println("第二次追加元素后names的长度:",len(names)," 容量:",cap(names))
nums := []int{}
for i:=0;i<50 ;i++ {
nums = append(nums, i)
fmt.Println("第",i,"nums长度:",len(nums)," nums容量:",cap(nums))
}
}
小结:
- 可以使用append进行追加数据
- len获取长度,cap获取容量
- 如果容量不足,且不大时,再次追加数据时,会动态分配2配空间
数组的切片截取
package main
import "fmt"
func main() {
// 数组的切片截取
names := [6]string{"北京","上海","广州","深圳","南京","武汉"}
// 切片可以基于一个数组灵活的创建新的数组
names2 := names[0:3] // 左闭右开
fmt.Println(names2) // [北京 上海 广州]
// 1.如果从开头起,冒号左面可以省略
names3 := names[:5] // [北京 上海 广州 深圳 南京]
fmt.Println(names3)
// 2.如果截取到尾部,冒号右面可以省略
names4 := names[1:] //[上海 广州 深圳 南京 武汉]
fmt.Println(names4)
// 修改同步
names4[0] = "三亚"
fmt.Println(names) //[北京 三亚 广州 深圳 南京 武汉]
// 3.如果全要,冒号左右都可以省略
names5 := names[:]
fmt.Println(names5)
// 如果想要让切片完全独立于原数组,可以使用copy()函数完成
//4.也可以基于一个字符串进行切片
sub1 := "Hello,go"[6:8]
fmt.Println(sub1)
//5.创建切片的时候,明确指定切片容量
// 用make实现,指定长度和容量
// 创建容量是20,长度为10的string类型切片---最常用的
// 第三个参数可以不写,默认与第二个相同
str_buff := make([]string,10,20) // 一次性分配成本低
// str_buff:len: 10
fmt.Println("str_buff:len:",len(str_buff))
// str_buff:cap: 20
fmt.Println("str_buff:cap:",cap(str_buff))
str_buff[0] = "hello "
str_buff[1] = "world!"
fmt.Println(str_buff)
//6.深拷贝,完全独立于原数组
new_names := []string{"北京","上海","广州","深圳","南京","武汉","杭州"}
copy_new_names := make([]string,len(new_names))
// 数组转换为切片就用加上冒号把数组变为切片(src []Type)
copy(copy_new_names,new_names[:])
copy_new_names[2] = "香港"
fmt.Println(copy_new_names)
fmt.Println(new_names)
}