zoukankan      html  css  js  c++  java
  • Go语言学习笔记(四)

    一、字符串

    1、字符串截取

    • 可以使用len(字符串变量)获取字符串的字节长度,其中英文占1个字节长度,中文占用3个字节长度

    • 可以使用变量名[n]获取到字符串第n+1个字节,返回这个字节对应的Unicode码值(uint8类型),注意n的取值范围是[0,长度)

      package main
      
      import "fmt"
      
      func main() {
      
      	s := "smallming张"
      	a := s[0]
      
      	fmt.Println(a)            // 115
      	fmt.Printf("%T
      ", a)     // unit8
      	b := fmt.Sprintf("%c", a) // string
      	fmt.Printf("%T
      ", b)     // s
      	fmt.Println(b)
      }
      
    • 可以使用变量名[n:m]取出大于等于n小于m的字符序列

      • n和m都可以省略,省略是认为n为0,m为长度减一
      • 因为中文占用三个字节,如果没有把中文完整取出,会出现乱码
      func main() {
      
         s := "smallming张"
      
         fmt.Println(len(s))  //12
         fmt.Println(s[1:4])  //mal
         fmt.Println(s[:4])   //smal
         fmt.Println(s[5:11]) //ming�
         fmt.Println(s[5:12]) //ming张
      }
      
    • 可以通过把字符串转换为切片获取长度,并获取里面内容,也可以直接使用for循环结合range获取

      func main() {
      
         s := "smallming张"
      
         s1 := []rune(s)
         fmt.Println(len(s1))
         fmt.Println(s1[9])
         fmt.Printf("%c", s1[9])
      
         for i, n := range s {
            fmt.Println(i, n)
         }
      }
      

    2、常用函数

    • 在strings包中提供了字符串常用的函数

    • 常用函数整理如下:

      func main() {
      
         s := "smallming"
      
         //第一次出现的索引
         fmt.Println(strings.Index(s, "l"))
      
         //最后一次出现的索引
         fmt.Println(strings.LastIndex(s, "l"))
      
         //是否含有前缀
         fmt.Println(strings.HasPrefix(s, "small"))
      
         //是否含有后缀
         fmt.Println(strings.HasSuffix(s, "ming"))
      
         //是否包含
         fmt.Println(strings.Contains(s, "mi"))
      
         //转换为小写
         fmt.Println(strings.ToLower(s))
      
         //转换为大写
         fmt.Println(strings.ToUpper(s))
      
         //替换字符,把字符串中前n个old子字符串替换成new字符串,如果n小于0表示全部替换
         fmt.Println(strings.Replace(s, "m", "k", -1))
      }
      

    二、常量

    1、概述

    • 常量是一个固定值,在编译期间就确定结果,声明时必须赋值且结果不可以改变
    • 因为常量在编译期间就确定,可以防止程序运行过程中意外修改
    • 常量关键字const
    • 常量定义后可以不使用
    • Go语言中常量定义没有明确语法要求,驼峰即可
    • 很多内容都可以定义成常量
      • 人名
      • 圆周率
      • 电话号

    2、常量定义

    • 定义常量时如果不是必须指定特定类型,可以省略类型,使用默认类型,且数值类型常量(不定义类型)可以直接进行运算

    • 常量的值可以是表达式,但是不允许出现变量

      func main() {
      
         const a string = "smallming"
         const b = 123
         const c = 3*2 + 5
      
         const d = 1.5
      
         fmt.Printf("%T %T
      ", c, d) //int float64
         fmt.Println(c + d)          //12.5
      
         //下面方式是错误的
         i := 3
         const e = i*3 + 2
      }
      
    • 当定义多个常量时官方推荐的方式

      // 定义常量组
      const (
         a = 1
         b = 2
         c = true
      )
      
    • 定义多常量时后一个常量如果没有赋值,与前一个常量值相同

      • 第一个常量必须赋值
      func main() {
      
         const (
            a = 1
            b
            c
         )
         fmt.Println(a, b, c) //1 1 1
      }
      

    3、常量生成器

    • 当一组常量都是数值类型,可以使用常量生成器iota指定这组常量按照特定规则变化

    • iota起始值为0,每次增加1

      func main() {
      
         const (
            a = iota
            b
            c
         )
         fmt.Println(a, b, c) //0 1 2
      
         const (
            d = iota << 1
            e
            f
         )
         fmt.Println(d, e, f) //0 2 4
      }
      
    • 无论是否使用iota,一组常量中每个iota值是固定的,iota按照顺序自增1

    • 每组iota之间无影响

      func main() {
      
         const (
            a = 5
            b = 3
            c = iota
            d
         )
         fmt.Println(a, b, c, d) //5 3 2 3
      
         const (
            e = iota
            f
            g = 10
            h
            i = iota
            j
         )
         fmt.Println(e, f, g, h, i, j) //0 1 10 10 4 5
      }
      

    三、指针

    1、变量地址

    • 变量本质就是内存中一块数据的标记,把值存储到变量中实质是把值存储到内存中

    • 每次对变量重新赋值就是在修改变量地址中的内容

    • 在Go语言中可以通过&+变量名获取到变量地址值

    • 重新创建一个非引用变量(即使是把已有变量直接赋值给新变量)也会新开辟内存地址

      func main() {
      
         a := 3
         fmt.Println(&a)
      
         a = 4
         fmt.Println(&a)
      
         b := a
         b = 5
         fmt.Println(&b, &a) //两个值不同
         fmt.Println(b, a)   //5 4
      }
      

    2、指针变量

    • 指针变量指向一个值的内存地址

    • 使用&+变量返回值就是一个指针类型

    • 使用var 变量名 *类型声明指针类型变量

    • 声明指针不会开辟内存地址,只是准备要指向内存某个空间,而声明变量会开辟内存地址,准备存放内容,所以指针类型变量都是把一个变量的地址赋值给指针变量

    • 使用*+指针能够获取内存地址中的值,所以*+指针就和直接使用变量是相同的

    • 应用指针可以实现多个地方操作同一内存地址的值

      func main() {
         var point *int
         fmt.Println(point) //nil
      
         a := 123
         point = &a
         fmt.Println(point)
      
         *point = 456
         fmt.Println(*point, a) //456 456
      }
      

    3、空指针

    • 指针目的就是指向内存中一块地址
    • 声明指针后指针不会指向任何内存地址,所以此时指针是空的,在Go语言中空用nil表示

    四、new函数

    • 上一节学习了指针,每次创建一个指针必须在额外创建一个变量,操作比较麻烦

    • 可以通过new函数直接创建一个类型的指针

      变量名 := new(type)
      
    • 使用new函数创建的指针已有指向,可以直接使用*指针对象进行赋值

    • 只声明的指针变量不能直接赋值,只能被赋值为另外一个已初始化的变量地址

      func main() {
         a := new(int)
         fmt.Println(a)
      
         *a = 123
         fmt.Println(*a)
      
         var b *int
         *b = 345
         fmt.Println(*b) //panic: runtime error: invalid memory address or nil pointer dereference
      }
      

    五、随机数

    • math/rand实现了伪随机数生成器

    • 在Go语言中随机数需要设置种子,如果不设置种子随机数的结果每次运行都相同

    • 默认种子是1,且相同种子产生的随机数是相同的

    • 可以使用当前时间的纳秒数计算随机数,在一定程度上保证了种子的唯一性

      func main() {
         fmt.Println(rand.Int63n(10))
         fmt.Println(rand.Int63n(6))
         fmt.Println(rand.Int63n(5))
      
         rand.Seed(time.Now().UnixNano())
      
         fmt.Println(rand.Int63n(10))
         fmt.Println(rand.Int63n(6))
         fmt.Println(rand.Int63n(5))
      }
      

    六、数组

    1、介绍

    • 数组:具有固定长度的相同类型元素序列

    • 声明数组的语法

      // var 对象名 [长度]元素类型
      var arr [5]int
      fmt.Println(arr) // 0 0 0 0 0
      
    • 数组就是内存中一段固定长度的连续空间

    • 声明数组后数组就会在内存中开辟一块连续空间,每个值称为数组的元素,且元素值为类型对应的默认值,例如int类型默认值为0,string类型默认值为空字符串

    • 数组中每个元素按照顺序都有自己整数类型的脚标,脚标从第一个元素为0向后依次加1

    • 实际开发中数组主要作用是充当临时容器,因为声明一个数组变量比声明多个相同类型变量在操作时更加方便

    2、数组的创建和赋值

    • 可以在声明数组时同时给数组赋值,赋值时要求长度必须大于等于初始值个数

      func main() {
         //完整写法
         var arr1 [3]int = [3]int{1, 2, 3}
      
         //短变量方式
         arr2 := [3]int{1, 2, 3}
      
         //长度大于初始值个数,长度为4,只给前三个元素赋值,其余元素为默认值
         arr3 := [4]int{1, 2, 3}
      
         //赋值时不写长度,数组长度根据元素个数确定
         arr4 := [...]int{1, 2, 3}
         fmt.Println(arr1, arr2, arr3, arr4)
      }
      
    • 可以通过数组名[脚标]对数组中元素进行操作

    • 通过len(数组变量)获取数组长度,数组脚标最大值为长度减一,如果超出这个范文将会报错

    3、数组是值类型

    • 在Go语言中数组是值类型,和之前学习的int或float64等类型相同,把一个数组变量赋值给另一个数组变量时为复制副本,重新开辟一块空间

    七、循环

    • 循环:让程序多次执行相同的代码块

    • for循环是Go语言中唯一一个循环结构

    • for循环用的最多的地方就是遍历数组或切片等

      func main() {
         arr := [2]int{1, 2}
      
         //遍历数组方式1
         for i := 0; i < len(arr); i++ {
            fmt.Println(arr[i])
         }
      
         //遍历数组方式2
         //i 脚标
         //n 元素内容 n = arr[i]
         for i, n := range arr {
            fmt.Println(i, n)
         }
      }
      
    • 冒泡排序

      func main() {
         arr := [5]int{1, 7, 6, 3, 2}
      
         for i := 0; i < len(arr)-1; i++ {
            for j := 0; j < len(arr)-i-1; j++ {
               if arr[j] > arr[j+1] {
                  arr[j], arr[j+1] = arr[j+1], arr[j]
               }
            }
         }
         fmt.Println(arr)
      }
      
    • 循环标签名,多重for循环中,可以定义for标签名

  • 相关阅读:
    4.23计算机网络
    CF436F Banners
    CF1467C Three Bags
    LG P3247 [HNOI2016]最小公倍数
    LG P5473 [NOI2019] I 君的探险
    LG P3261 [JLOI2015]城池攻占
    LG P4149 [IOI2011]Race
    LG P3181 [HAOI2016]找相同字符
    SP7258 SUBLEX
    SP1811 LCS
  • 原文地址:https://www.cnblogs.com/wenha/p/12313449.html
Copyright © 2011-2022 走看看