• Go语言学习笔记(二)


    一、字符

    1、概述

    • 字符型存放单个字母或单个文字
    • GO语言不支持字符类型,在GO语言中所有字符值都转换为对应的编码表中int32值
    • GO语言默认使用UTF8编码

    2、编码发展历史

    • 最开始使用8个可开合晶体管表示世间万物,这就是字节的由来,后来生产出可以控制字节的机器,出现了计算机
    • 把字节中32以下情况称为控制码,后再控制码基础上添加空格、标点符号、数字、大小写字母等直到127,最终形成了ASNI的ASCII码,这是已经较好的支持英文了
    • 随着计算机在全球的应用,在原ASCII基础上添加了新的字母、符号、横线竖线等直到255号,从128到255被称为扩展字符集,但是此时计算机还是在支持英文
    • 等中国开始使用计算机,为了支持中文,保留了前127号,这些称为半角,把后面的内容以两个字节拼接形成中文汉字和表单符号,这后半部分就是全角,其中汉字6763个满足中文大部分情况的要求称为GB2312
    • 随着计算机在中国的普及,使用GB2312时有的汉字无法打出,又在GB2312基础上添加了近20000个汉字(包含繁体和符号等)形成GBK,后来为支持少数民族又在GBK基础上退出了GB18080
    • 全球中每个国家都有自己的一套编码,ISO国际为了统一标准,重新定义了一套编码,希望包含全球所有的文字和符号,俗称Unicode
    • 随着互联网的快速发展,为缓解Unicode网络传输中流量浪费问题,出现了UTF编码,有UTF-8(8位传输)和UTF-16(16位传输)两种,其中UTF-8使用最多,为变长编码方式,中文占3个字节

    二、转义字符

    1、转义字符介绍

    • 在GO语言中可以使用%+特定字母形成转义字符,这个表示特定含义的组合成为转义字符

    • 在GO语言中又称为verb

    • 转义字符在GO语言中以下两种情况使用频率较高

    fmt.Print("verb",内容)//输出
    fmt.Scanf("verb",接受变量)//输入
    

    2、进制描述

    • 进制数在编程中经常遇见,进制数分为二进制、八进制、十进制、十六进制,其中十进制就是平常我们接触最多的
    • X进制都满足:
      • 满X进一位
      • 每位最大为X-1
      • 第N位代表X的(n-1)次方
    • 其中十六进制中a=10,b=11,c=12,d=13,e=14,f=15

    3、常用转义字符汇总

    Verb 含义
    %d 十进制整数
    %x、%X 大小写方式显示十六进制整数
    %o 八进制整数
    %b 二进制整数
    %f、%g、%e 浮点数
    %t 布尔值
    %c 字符
    %s 字符串
    %q 带双引号字符串
    %v 内置格式内容
    %T 类型
    %p 内存地址
    %% 字符%
    换行
    缩进

    三、用户输入

    1、简介

    • 用户输入在平时练习中使用频率较高
    • 程序运行时,运行到接受用户输入语句会阻塞,等待用户输入,用户输入后,把内容赋值给对应的变量后,程序继续运行
      • 在GO语言中有多重接受用户输入的方式,其中使用fmt包的Scan函数使用最简单

    2、接收用户输入的几种方式

    • 使用Scanln(&变量名,&变量名)的方式接收

      • 输入的内容必须都在同一行
      • 每个内容之间使用空格分隔
      • 回车换行后表示停止输入
      • 如果希望接收3个值,而在控制台只输入2个值,回车后也停止接收
      • 如果希望接收2个值,而在控制台输入3个,回车后只能接收两个值
    package main
      
    import "fmt"
      
    func main() {
    	var name, age string
    	fmt.Print("请输入用户姓名和年龄:")
    	fmt.Scanln(&name, &age)
    	fmt.Println("接收到内容为:", name, age)
    }
    
    • 也可以使用fmt.Scanf(verb,&变量)按照特定的格式进行输入

      • 下面例子演示的每次换行输入一个内容
    package main
      
    import "fmt"
      
    func main() {
       var a, b string
       fmt.Println("请输入姓名和年龄:")
       fmt.Scanf("%s
    %s", &a, &b)
       fmt.Printf("%s
    %s", a, b)
    }
    
    • 需要注意,如果同行输入两个字符串,中间使用空格,否则编译器无法对输入内容进行拆分

    四、输出

    1、打印输出

    • 在程序中输出使用频率很高,使用输出语句可以再程序执行过程中把一些结果输出到控制台,程序员通过控制台中输出结果判断是否符合预期
    • 在GO语言中有多重输出方式,不同的输出适用场景不同,归纳起来三类,每类又分为三种(原内容、原内容+ln、原内容+f)
      • PrintXX()
      • FprintXX()
      • SprintXX()

    2、FprintXX()

    • FprintXX在Go Web中使用比较多,把内容写到响应中
    • 以Fprintln()举例,源码如下:
    // Fprintln formats using the default formats for its operands and writes to w.
    // Spaces are always added between operands and a newline is appended.
    // It returns the number of bytes written and any write error encountered.
    func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
    	p := newPrinter()
    	p.doPrintln(a)
    	n, err = w.Write(p.buf)
    	p.free()
    	return
    }
    
    • 函数参数中第一个参数是输出流,后面参数是内容,表示把内容写入到输出流中

    • 第一个返回值表示输出内容长度(字节数),第二个返回值表示错误,如果没有错误取nil

      • Fprintln()输出后会添加换行符,所以长度比内容多1个
      • Fprintln()源码中p.doPrintln(a)的源码
    // doPrintln is like doPrint but always adds a space between arguments
    // and a newline after the last argument.
    func (p *pp) doPrintln(a []interface{}) {
    	for argNum, arg := range a {
    		if argNum > 0 {
    			p.buf.writeByte(' ')
    		}
    		p.printArg(arg, 'v')
    	}
    	p.buf.writeByte('
    ')
    }
    
    • FprintXX()支持下面三种方式

      • os.Stdout表示控制台输出流
    func main() {
    	fmt.Fprint(os.Stdout, "内容1")//向流中写入内容
    	fmt.Fprintln(os.Stdout, "内容2")//向流中写入内容后额外写入换行符
    	fmt.Fprintf(os.Stdout, "%s", "内容3")//根据verb格式向流中写入内容
    }
    

    3、PrintXX

    • PrintXX支持以下三种方式
    func main(){
    	fmt.Println("内容1")//输出内容后换行
    	fmt.Print("内容2")//输出内容后不换行
    	fmt.Printf("verb","内容")//根据verb输出指定格式内容
    }
    
    • 以Println()举例,源码如下
    // Println formats using the default formats for its operands and writes to standard output.
    // Spaces are always added between operands and a newline is appended.
    // It returns the number of bytes written and any write error encountered.
    func Println(a ...interface{}) (n int, err error) {
       return Fprintln(os.Stdout, a...)
    }
    
    • 可以看出Println()底层实际是Fprintln(),返回值依然是内容长度和错误信息

    4、SPrintXX

    • 以SPrintln() 为例,和Println()主要的区别是:
      • Sprintln()把形式结果以字符串返回,并没有打印到控制台
      • Println()把结果打印到控制台,返回内容长度和错误
    • 所以严格意义角度讲SprintXX不是打印输出,而更像字符串转换
    • 源码如下
    // Sprint formats using the default formats for its operands and returns the resulting string.
    // Spaces are added between operands when neither is a string.
    func Sprint(a ...interface{}) string {
       p := newPrinter()
       p.doPrint(a)
       s := string(p.buf)
       p.free()
       return s
    }
    
    • 也有三种方式
    fmt.Sprint("内容1", "内容2")
    fmt.Sprintf()
    fmt.Sprintln("1", "2")
    

    五、变量声明和赋值

    1、静态语言和动态语言

    • 静态类型语言和强类型语言是同一个意思,表示在编译器就确定了类型,而且类型是不可以改变的
    • 动态类型语言和弱类型语言是同一个意思,表示在运行过程中才能确定且内容是什么类型变量类型跟随变化

    2、GO语言变量简介

    • go语言和其他语言一样都有基本存储容器,可以存储一个或多个值在程序中,方便程序中多次使用容器中内容,这个容器称为变量
    • GO语言虽然是静态类型语言,但是支持动态类型语言语法,因为GO语言希望程序员少声明变量,增加GC效率

    3、变量命名规则

    • 以字母或下划线开头(GO语言多不以_开头)
    • 后面可以是任意数量的字符、数字和下划线
    • 区分大小写
    • 不能是关键字(关键字具备特定含义),下面是GO语言的关键字
    关键字如下
    break default func interface select
    case defer go map struct
    chan else goto package switch
    const fallthrough if range type
    continue for import return var
    • 可以是保留字,但是不建议使用保留字作为变量名,下面是GO语言的保留字
    保留字如下
    true false iota nil int
    int8 int16 int32 int64 unit
    unit8 unit16 unit32 unitptr float32
    float64 complex128 complex64 bool byte
    rune string error make len
    cap new append copy close
    deletecomplex real image panic recover
    • 在同一范围内不允许出现同名变量
    • GO语言要求变量声明后至少使用一次

    4、单个变量声明及赋值

    • 先声明后赋值(声明后开辟内存,不同类型变量都有不同初始值)
    //语法
    //1.声明
    var 变量名 类型
    //2.赋值
    变量名=值
    
    • 声明并赋值(此方式不建议)
    //语法
    var 变量名 类型 = 值
    
    //实例
    var smallming string = "英文名"
    
    • 声明并赋值(省略类型,变量类型取决于值的类型)
    //语法
    var 变量名 = 值
    
    • 短变量(只能在函数内使用)
    //语法
    变量名 := 值
    

    5、声明多个变量

    • 先声明后赋值
    func main(){
    	var a,b,c int
    	a,b,c = 1,2,3
    	fmt.Println(a,b,c)
    }
    
    • 声明时赋值
    func main(){
    	var a,b,c,d = 1,2,3,false
    	fmt.Println(a,b,c,d)
    }
    
    • 声明并赋值,推荐方式
    func main(){
    	var (
    		a = 1
    		b = true
    		c = "测试"
    	)
    	fmt.Println(a,b,c)
    }
    
    • 使用短变量给多个变量赋值时,必须要保证至少有两个变量没有声明的
    func main(){
        var (
            a = 1
            b = true 
            c = "测试"
        )
        b,c,d := false, "smallming", 3
        fmt.Println(a,b,c,d)
    }
    

    六、整型

    1、概述

    • 在GO语言中可以进行数据运算的类型分为整型和浮点型

    • 所有的整数数字存储到整型中就可以进行数学运算

      • 整型和整型运算的结果还是整型(5/2=2)
      • 都是整型,但是int8 和int16之间不可以进行运算,必须进行类型转换
    • 整型分为有符合整型和无符号整型

      • 有符号整型有正数和负数,其二进制最高位表示符号,0为正数1为负数,int和intx为有符号整型
    • 无符号整型只能取大于等于0的整数,其二进制最高位表示真实数字,unit和unitx为无符号整型

    • 整型取值范围和作用

      • 有符号整数统一公式为:-2的n-1次幂到2的n-1次幂减1
    • 无符号整数统一公式为

    类型 取值范围
    int8 [-128,127]
    int16 [-32768,32767]
    int32 [-2147483648,2147483647],GO语言没有字符类型,所有字符都使用int32
    int64 [-92233722036854775808,9223372036854775807]
    int 受限于计算机系统,系统是多少位,int为多少位
    unit8 [0,255]
    unit16 [0,65535]
    unit32 [0,4294967295]
    unit64 [0,18446744073709551615]
    uint 受限于计算机系统,系统是多少位,uint为多少位
    rune 与int32类似,常用在获取值的Unicode码
    byte 与uint8类似,强调值为原始数据,一个字节占用8个二进制
    uintptr 大小不确定,类似取决于底层编程

    2、类型转换

    • GO语言是静态类型语言,并且不具备低精度向高精度自动转换功能,所以不同类型变量之间相互赋值需要进行类型转换
    package main
    
    import "fmt"
    
    func main() {
    	//声明3个类型变量
    	var a int = 1
    	var b int32 = 2
    	var c int64 = 3
    
    	fmt.Println(a, b, c)
    
    	//把int32转换为int64
    	a = int(b)
    	fmt.Println(a, b)
    	a = 1
    
    	//把int64转换为int32
    	b = int32(c)
    	fmt.Println(b, c)
    	b = 2
    
    	//把int转换为int64
    	c = int64(a)
    	fmt.Println(a, c)
    	c = 3
    }
    

    3、不同进制整数

    • 支持八进制、十进制、十六进制数字创建整型,最后由系统转换为十进制
    • 不支持二进制值
    package main
    
    import "fmt"
    
    func main() {
    	//默认表示十进制
    	d := 17
    
    	//0开头表示八进制
    	o := 021
    
    	//0x开头表示十六进制
    	x := 0x11
    
    	//e2表示10的2次方
    	e := 11e2
    
    	//输出
    	fmt.Println(d, o, x, e)
    
    	//把变量d中内容转为二进制
    	b := fmt.Sprintf("%b", d)
    	fmt.Println(b)
    }
    
  • 相关阅读:
    redis 持久化RDB、AOF
    进程、线程、协程
    nginx 常用配置
    Redis详解(一)
    Nginx(一)
    docker compose
    练习1——排序
    8万行的insert数据,Ctrl+c、Ctrl+v后心态崩了(如何在Linux下对MySQL数据库执行sql文件)
    Ubuntu使用+Thinkphp5学习——20(html文件中代码注释掉,但是runtime/temp中的php文件仍然存在)
    Ubuntu使用+Thinkphp5学习——19(新增用户报错strip_tags() expects parameter 1 to be string, array given)
  • 原文地址:https://www.cnblogs.com/wenha/p/12291731.html
Copyright © 2020-2023  润新知