Golang学习笔记01

06-21 1383阅读

变量的数据类型

整数数据类型

  • 有符号类型 int8 int16 int32 int64
  • 无符号类型 uint8 uint16 uint32 uint64

    浮点数据类型

    • float32 4字节
    • float64 8字节

      布尔型

      package main
      import (
      	"fmt"
      )
      func main() {
      	var s = true
      	fmt.Println(s)
      }
      

      字符串

      不可变:指的是字符串一旦定义好,其中字符的值不可以改变,如果输入特殊字符,字符串形式为反引号

      Golang学习笔记01
      (图片来源网络,侵删)
      package main
      func main() {
      	var s1 = `
      	var s = true
      	println(s)`
      	println(s1)
      }
      

      可以保留原有的输入的内容

      类型转化

      只能进行强类型转化,不支持自动类型转化,原有的类型不变,只是将数值转化

      package main
      func main() {
      	var a = 101
      	var b = string(a)
      	println(b)
      }
      

      注意:int64转化为int8时编译不会出错,但是数值会溢出

      其他类型转化为String

      使用Sprintf函数进行转化

      package main
      import "fmt"
      func main() {
      	//其他类型转化为String类型
      	//fmt.Sprintf()使用中需要注意转换的格式,int 为%d, float 为%f, bool为%t, byte 为%c
      	var a int = 20
      	var b float64 = 12.456
      	var c bool = true
      	var d byte = 'a'
      	var stra, strb, strc, strd string
      	stra = fmt.Sprintf("%d", a)
      	strb = fmt.Sprintf("%f", b)
      	strc = fmt.Sprintf("%t", c)
      	strd = fmt.Sprintf("%c", d)
      	//输出值的类型%T,占位符%v
      	fmt.Printf("stra type is %T, value is %v \n", stra, stra)
      	fmt.Printf("strb type is %T, value is %v \n", strb, strb)
      	fmt.Printf("strc type is %T, value is %v \n", strc, strc)
      	fmt.Printf("strd type is %T, value is %v \n", strd, strd)
      }
      

      使用strconv函数进行转化

      package main
      import (
      	"fmt"
      	"strconv"
      )
      func main() {
      	var n1 int = 18
      	//参数:第一个参数:传入int64位的一个整数,第二个参数:你需要转化的进制数
      	var s1 = strconv.FormatInt((int64(n1)), 10)
      	fmt.Printf("s1对应的类型是:%T,s1 = %q", s1, s1)
      	println()
      	//参数:第一个参数:需要转化的数,第二个参数:‘f’(-ddd.dddd),第三个参数:小数点的保留位数,第四个参数:转化为int64
      	var n2 float64 = 4.21
      	var s2 = strconv.FormatFloat(n2, 'f', 4, 64)
      	fmt.Printf("s2对应的类型是:%T,s2 = %q", s2, s2)
      	println()
      	var n3 = true
      	var s3 = strconv.FormatBool(n3)
      	fmt.Printf("s3对应的类型是:%T,s3 = %q", s3, s3)
      }
      //运行结果:
      //s1对应的类型是:string,s1 = "18"
      //s2对应的类型是:string,s2 = "4.2100"
      //s3对应的类型是:string,s3 = "true" 
      

      string类型转化为其他类型

      package main
      import (
      	"fmt"
      	"strconv"
      )
      func main() {
      	var a = "123"
      	var a1, err = strconv.ParseInt(a, 10, 64)
      	fmt.Printf("类型是:%T,值是%v,%v", a1, a1, err)
      	println()
      	//非数字字符不能转化为int
      	var b = "hello"
      	var b1, err1 = strconv.ParseInt(b, 10, 64)
      	fmt.Printf("类型是:%T,值是%v,%v", b1, b1, err1)
      	println()
      	var c = "true"
      	var c1, _ = strconv.ParseBool(c)
      	fmt.Printf("类型是:%T,值是%v", c1, c1)
      }
      

      指针

      package main
      func main() {
      	var i int = 10
      	println("i的值", i)
      	//指针类型
      	var ptr *int = &i
      	println("i的地址", ptr)
      	println("ptr的地址", &ptr)
      	println("ptr指向的值", *ptr)
      }
      /*
      输出结果:
      i的值 10
      i的地址 0xc00005ff28
      ptr的地址 0xc00005ff38
      ptr指向的值 10
      */
      

      注意点

      1. 指针可以改变具体的值
      2. 指针变量接受的是地址
      3. 指针的地址不可以不匹配

      流程控制语句

      package main
      import "fmt"
      func main() {
      	//流程控制语句
      	var a = 10
      	if a > 10 {
      		fmt.Println(1)
      	} else {
      		fmt.Println(2)
      	}
      	//switch循环
      	switch 10 / 2 {
      	case 1:
      		println(1)
      	case 2:
      		println(2)
      	default:
      		println(3)
      	}
      	//for循环
      	for i := 0; i  
       
       

      goto用法

      package main
      import "fmt"
      func main() {
      	fmt.Println(1)
      	fmt.Println(2)
      	if 1 == 1 {
      		goto label1
      	}
      	fmt.Println(3)
      	fmt.Println(4)
      	label1:
      	fmt.Println(5)
      }
      

      函数

      package main
      import "fmt"
      func main() {
      	//调用
      	var res = sum(1, 2)
      	fmt.Println(res)
      }
      func sum(a int, b int) int {
      	return a + b
      }
      

      首字母大写该函数可以被本包文件和其他包使用(public),首字母小写只能被本包使用(private)


      通过地址交换两个数

      package main
      import "fmt"
      func main() {
      	//调用
      	var a = 10
      	var b = 20
      	fmt.Println(a, b)
      	swap(&a, &b)
      	fmt.Println(a, b)
      }
      func swap(a *int, b *int) {
      	var t = *a
      	*a = *b
      	*b = t
      }
      

      ps:go中不支持重载,支持可变参数

      go函数可以作为一个数据类型,赋值给一个变量

      package main
      import "fmt"
      func test(num int) {
      	fmt.Println(num)
      }
      func main() {
      	var a = test
      	fmt.Printf("a的类型是%T,test的类型为%T \n", a, test) //a的类型是func(int),test的类型为func(int)10
      	a(10) //等价与test(10)
      }
      

      自定义数据类型

      package main
      import "fmt"
      func main() {
      	//自定义数据类型:相当于起别名
      	type myInt int
      	var num1 myInt = 10
      	//num1的类型是main.myInt,num1的值为10
      	fmt.Printf("num1的类型是%T,num1的值为%v", num1, num1)
      }
      

      函数的返回值可以支持命名,里面的顺序可以不一样

      package main
      import "fmt"
      func test1(num1 int, num2 int) (sum int, sub int) {
      	sub = num1 - num2
      	sum = num1 + num2
      	return sum, sub
      }
      func main() {
      	var n1 = 10
      	var n2 = 5
      	var sum, sub = test1(n1, n2)
      	fmt.Println(sum, sub)
      }
      

      init函数

      每一个源文件包含一个init函数,该函数会在main函数调用前,被go框架所执行

      package main
      import "fmt"
      func init() {
      	fmt.Println("init被执行")
      }
      func main() {
      	fmt.Println("main被执行")
      }
      //init被执行
      //main被执行
      

      匿名函数

      只希望被调用一次,可以使用到匿名函数,定义的同时被调用

      package main
      import "fmt"
      // 让匿名函数在全局有效
      var Mul = func(num1 int, num2 int) int {
      	return num1 * num2
      }
      func main() {
      	//定义匿名函数
      	var res = func(num1 int, num2 int) int {
      		return num1 + num2
      	}(10, 20)
      	fmt.Println(res)
      	//将匿名函数赋值给一个变量,这个变量实际上是函数类型的变量
      	//sub等价于匿名函数
      	sub := func(num1 int, num2 int) int {
      		return num1 - num2
      	}
      	//调用sub
      	res01 := sub(50, 20)
      	fmt.Println(res01)
      	var res02 = Mul(2, 3)
      	fmt.Println(res02)
      }
      

      闭包

      返回的匿名函数+匿名函数以外的变量 = 闭包

      闭包的值会一直保存到内存中

      package main
      import "fmt"
      // 闭包
      func getSum() func(int) int {
      	var n = 10
      	return func(i int) int {
      		n = n + i
      		return n
      	}
      }
      func main() {
      	f := getSum()
      	fmt.Println(f(1))//11
      	fmt.Println(f(1))//12
      }
      

      defer 关键字

      package main
      import "fmt"
      func main() {
      	fmt.Println(add(30, 60))
      }
      func add(num1 int, num2 int) int {
      	//在Golang中程序遇到关键字defer不会立即执行,而是将defer后的语句压入栈中,继续执行函数后的语句
      	defer fmt.Println("num1=", num1)
      	defer fmt.Println("num2=", num2)
      	var sum = num1 + num2
      	fmt.Println("sum=", sum)
      	return sum
      }
      /*
      按照先进后出的规则
      sum= 90
      num2= 60
      num1= 30
      90
       */
      

      应用场景:想要关闭某些资源时,在前面加入defer关键字,因为defer有延迟机制

      系统函数

      package main
      import (
      	"fmt"
      	"strconv"
      	"strings"
      )
      func main() {
      	//1.统计字符串
      	var str = "golang你好"  //Golang中汉字是utf-8字符集,一个汉字三个字节
      	fmt.Println(len(str)) //12
      	//2.对字符串进行遍历 方式一
      	//索引为0,值为g
      	//索引为1,值为o
      	//索引为2,值为l
      	//索引为3,值为a
      	//索引为4,值为n
      	//索引为5,值为g
      	//索引为6,值为你
      	//索引为9,值为好
      	for i, value := range str {
      		fmt.Printf("索引为%d,值为%c \n", i, value)
      	}
      	//方式二利用切片
      	//'g''o''l''a''n''g''你''好'
      	var r = []rune(str)
      	for i := 0; i  
      
      package main
      import (
      	"fmt"
      	"strings"
      )
      func main() {
      	//9.字符串替换 n=-1表示全部替换,替换两个n=2
      	var str = strings.Replace("golangandjava", "go", "golang", 2)
      	fmt.Println(str)
      	//10.切割
      	var str1 = strings.Split("go-java-c++", "-")
      	fmt.Println(str1) //[go java c++]
      	//11.大小写转化
      	strings.ToLower("A")
      	strings.ToUpper("a")
      	//12.去除空格
      	strings.TrimSpace(" goandjava ")
      	//13.去除左右两边指定字符
      	strings.Trim("-javago-", "-")
      	//14.判断字符是否是指定字符开头,结尾
      	strings.HasPrefix("http://123.123", "http")
      	strings.HasSuffix("http://123.123", "123")
      }
      

      日期函数

      package main
      import (
      	"fmt"
      	"time"
      )
      func main() {
      	//日期函数
      	var now = time.Now()
      	//返回值的类型是一个结构体
      	fmt.Printf("类型是%T \n", now) //time.Time
      	fmt.Println(now)            //2024-06-13 14:25:35.9049279 +0800 CST m=+0.002579401
      	year := now.Year()
      	month := now.Month()
      	day := now.Day()
      	fmt.Println(year, month, day)
      }
      

      内置函数

      不需要导包,直接使用

      package main
      import "fmt"
      func main() {
      	var str = "golang"
      	fmt.Println(len(str))
      	//new函数分配内存,new函数的实参是一个类型而不是具体数值,返回值是对应类型的指针
      	var num = new(int)
      	fmt.Printf("num的类型是%T,num的值为%v,num的地址为%v,num指向的值为%v", num, num, &num, *num)
      	//num的类型是*int,num的值为0xc00000a0f8,num的地址为0xc000062030,num指向的值为0
      }
      

      错误处理机制

      使用defer+recover管理错误

      package main
      import "fmt"
      func main() {
      	//利用defer+recover+匿名函数捕获异常
      	defer func() {
      		var err = recover()
      		if err != nil {
      			fmt.Println("错误被捕获")
      			fmt.Println("错误是", err)
      		}
      	}()
      	var num1 = 10
      	var num2 = 0
      	var res = num1 / num2
      	fmt.Println(res)
      }
      

      自定义错误

      package main
      import (
      	"errors"
      	"fmt"
      )
      func main() {
      	err := test()
      	if err != nil {
      		fmt.Println("自定义错误", err)
      	}
      	fmt.Println("正常执行下面逻辑")
      }
      func test() (err error) {
      	num1 := 10
      	num2 := 0
      	if num2 == 0 {
      		//抛出自定义异常
      		return errors.New("除数不能为0")
      	} else {
      		fmt.Println(num1 / num2)
      		return nil
      	}
      }
      //自定义错误 除数不能为0
      //正常执行下面逻辑
      

      数组

      package main
      import "fmt"
      func main() {
      	var num [3]int
      	num[0] = 1
      	num[1] = 2
      	num[2] = 3
      	var sum int
      	for i := 0; i  
      

      数组默认是值传递,想要在外部修改原有的值,需要传递地址

      package main
      import (
      	"fmt"
      )
      func main() {
      	var arr = [...]int{1, 2, 3}
      	fmt.Println("原数组的值为", arr)
      	test(&arr)
      	fmt.Println("修改后数组的值为", arr)
      	//原数组的值为 [1 2 3]
      	//修改后数组的值为 [4 2 3]
      }
      func test(arr *[3]int) {
      	arr[0] = 4
      }
      

      二维数组

      package main
      import "fmt"
      func main() {
      	var arr = [2][3]int{{1, 2, 3}, {4, 5, 6}}
      	fmt.Println(arr)
      }
      

      切片

      建立在数组上的一种抽象,构建在数组之上,并且提供了更强大的能力,

      是对数组一个连续片段的引用,所以切片是一种引用类型,这个片段可以是整个数组

      或者是由起始和终结标识符的一些项的子集

      package main
      import "fmt"
      func main() {
      	var arr = [6]int{1, 2, 3, 4, 5, 6}
      	//切片构建在数组之上,左闭右开
      	var slice = arr[1:3]
      	fmt.Println(slice)
      	//切片的构建
      	var slice1 = make([]int, 4, 20)
      	fmt.Println("slice1的长度", len(slice1))
      	fmt.Println("slice1的最大容量", cap(slice1))
      	var slice2 = []int{1, 2, 3}
      	fmt.Printf("slice2的类型%T \n", slice2)
      	fmt.Println("slice2的长度", len(slice2))
      	fmt.Println("slice2的最大容量", cap(slice2))
      }
      

      可以实现动态扩容,底层是创建一个新数组将老数组复制到新数组中

      package main
      import "fmt"
      func main() {
      	var slice2 = []int{1, 2, 3}
      	var slice3 = append(slice2, 4, 5)
      	fmt.Println(slice3)//1,2,3,4,5
      }
      

      映射

      go中内置的数据类型,将键值进行关联,通过key获取val

      package main
      import "fmt"
      func main() {
      	//只声明是不会分配内存空间的
      	var a = make(map[int]string, 10)
      	a[1] = "张三"
      	a[2] = "李四"
      	a[3] = "王五"
      	fmt.Println(a)
      	var b = make(map[int]string)
      	b[1] = "张三"
      	b[2] = "李四"
      	fmt.Println(b)
      	var c = map[int]string{
      		1: "张三",
      		2: "李四",
      	}
      	fmt.Println(c)
      }
      

      面向对象

      package main
      import "fmt"
      type Person struct {
      	Name string
      	Age  int
      }
      func main() {
      	//方式一
      	var p1 = Person{
      		Name: "张三",
      		Age:  18,
      	}
      	fmt.Println(p1)
      	//方式二创建结构体的指针,应该给地址指向的字段赋值
      	var p2 *Person = new(Person)
      	(*p2).Name = "李四"
      	(*p2).Age = 20
      	fmt.Println(*p2)
      	//方式三
      	var p3 = &Person{
      		"王五",
      		30,
      	}
      	fmt.Println(p3)
      }
      
      package main
      import "fmt"
      type A struct {
      	Num int
      }
      // 方法与结构体是绑定关系,如果其他类型调用test会报错,并且是值传递
      func (a A) test() {
      	fmt.Println(a.Num)
      }
      func main() {
      	var p = A{
      		Num: 1,
      	}
      	p.test()
      }
      	a[3] = "王五"
      	fmt.Println(a)
      	var b = make(map[int]string)
      	b[1] = "张三"
      	b[2] = "李四"
      	fmt.Println(b)
      	var c = map[int]string{
      		1: "张三",
      		2: "李四",
      	}
      	fmt.Println(c)
      }
      
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]