Go 基础学习

99 阅读5分钟

Go学习之基础篇 day01

简介和准备

  1. go语言是一门编译语言,某种程度上替代java

变量

  1. var 变量名 变量类型 var age int
  2. bool,string,int,uint,byte(uint8的别名),rune(int32的别名,代表的是unicode编码),float32,complex(复数)
  3. 所有的内存在go中都是经过初始化的
  4. 不指明变量类型,在编译是会自动推导类型
  5. 批量声明的方式var(a int b string )
  6. 简短格式: a:=13--->只可以定义在函数内部,定义了变量一定要使用 var往往在需要显示声明的地方

出错的情况: 不可以进行重复声明,但是在多个短变量声明和赋值当中,至少有一个新声明的变量出现在左边值中,即使其他变量名可能是重复声明的,但是编译器也不会报错。 字符串其实是字节数组,但是只能获取ASCII码的索引(len),不能适用于unicode,unicode的长度,utf8.RuneCountInString(s)
字符串的拼接:+--》如果是大量字符串效率不高,使用bytes.Buffer
如果想在hello,world马神中获取马, v := string([]rune(s)[9])
print是标准输出,sprint结果会以字符串形式返回
字符串查找 strings.index(从头开始找第一个匹配的)he

类型转换

  1. 所有的类型转换都要显示声明
a:=5.0
b:=int(a)//显示的进行转换
fmt.Println(b)

只有相同底层的类型才可以进行转换。大精度的转换到小精度会导致精度缺失。

修改字符串

golang的字符串不可以改变,强制转换为byte[]进行修改

s1 := "localhost:8080"
b := []byte(s1)
b[len(b)-1] = '1'
s3 := string(b)
fmt.Println(s3)

小练习:将字符串“hello,码神之路之Java教程”替换成“hello,码神之路之Go教程”

s := "hello,码神之路之Java教程"
s1 := s[:strings.Index(s, "J")] + "Go" + s[strings.Index(s, "va")+2:]
fmt.Println(s1)

常量 const

只可以是bool,数字型,字符串型
iota常量生成器

指针

分类

  1. 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,无需进行数据拷贝,类型指针不能进行偏移和运算
  2. 切片,由指向起始元素的原始指针,元素数量以及容量组成
  • 如何理解指针:

import "fmt"

func main() {
   var a int = 10
   //空间中有一个地址的空间存放数值10,指向这个地址的变量就是指针,地址标识内存
   //&获取变量的内存地址
   ptr := &a
   *ptr = 30
   //*ptr标识这个变量,对指针进行取值
   fmt.Println(a)
}

变量,指针地址,指针变量,取地址,取值

  • 对变量进行取地址&,可以获取获得这个变量的指针变量
  • 指针变量的值就是指针地址
  • 对指针变量进行取值操作就是*,可以获得指针变量指向的原变量的值

使用指针进行修改值


import "fmt"

func main() {
   var a int = 10
   modifyFormPoint(a)
   fmt.Println(a)
   newmodifyFormPoint(&a)
   fmt.Println(a)
}
func modifyFormPoint(num int) {
   num = 10000
   fmt.Println("没有使用指针进行传值", num)
}
func newmodifyFormPoint(num *int) {
   *num = 10
   fmt.Println("没有使用指针进行传值", *num)
}
ptr := new(string)
//创建一个新的指针,没有赋值指向默认值
*ptr = "hellolcaa"
fmt.Println(*ptr)

获取命令行参数

var mode = flag.String("mode", "", "运行模式,可以设置为fast")

func main() {
   flag.Parse()
   fmt.Println(*mode)
}

image.png

变量的生命周期

go中有两种数据结构存放变量

  • 堆:存放在进程中执行被动态分配的内存段,大小并不确定,可以动态的扩张或者缩减;当进程调用malloc等函数分配内存是,新分配的内存就被动态加入到堆上,当利用free等函数释放内存的时候,被释放的内存从堆中剔除
  • 栈 :用来存放程序暂时创建的局部变量。 在程序的编译阶段,会自动选择在栈还是堆上分配局部变量的存储空间,不论使用var还是new关键字声明变量都不会影响编译器的使用。如果和堆上的变量可以找到这个变量,所以局部变量存储在堆上,所以就是函数逃逸了。

类型别名 type

type typealias = type
type name Type

  • 区别:类型定义和类型别名:类型是否会进行变化

字符串和其他类型转换

  • str转int
str := "1"
intiValue, _ := strconv.Atoi(str)//string转int
fmt.Println(intiValue)

strVlaue := strconv.Itoa(intiValue)//int转string
fmt.Printf("%T", strVlaue)
  • 浮点数和字符串转换
str := "1.345"
intiValue, _ := strconv.ParseFloat(str, 64)
fmt.Println(intiValue)
strVlaue := strconv.FormatFloat(intiValue, 'f', 2, 64)
fmt.Printf("%T", strVlaue)

获取标准输入

reader:=bufio.NewReader(os.Stdin)
input,err:=reader.ReadString('\n')
if err!=nil {
   panic(err)
}
fmt.Println(input)

数组

数组的长度是固定的,所以很少使用数组,数组长度必须是在编译时便确定长度的大小
var arr [3]int

  • 多维数组:尤其适合管理具有父子关系或者与坐标系相关联的数据

切片:

定义:可以容纳若干相同类型的元素的容器,无法通过切片类型来确定长度,每个切片值都会将数组作为底层数据结构,我们也把这杨的数组称为切片的底层数组
切片是对数组的一个连续片段的引用,所以切片是一个引用类型。

  • 直接声明切片: var name []Type

  • 直接使用make函数构造切片:make([]type,size,cap) 使用make()函数生成的切片一定发生了内存分配操作,但给定开始与结束位置(包括切片复位)的切片只是将新的切片结构指向已经分配好的内存区域,设定开始与结束位置,不会发生内存分配操作。 copy进行切片复制,源数据修改不会改变,如果是引用的话就会被改变,所以我们在定义使用切片复制的时候就可以进行分情况使用。