当前位置:   article > 正文

Go基础_go二进制转换unicode

go二进制转换unicode

Go

Google为什么要创建Go
  1. 计算机硬件技术更新频繁,性能提高很快。目前主流的变成语言发展明显落后于硬件,不能合理利用多核多CPU的优势提升软件系统性能
  2. 软件系统复杂度越来越高,维护成本越来越高,目前缺乏一个足够简洁高效的编程语言
    • 现有的编程语言存在的问题
      1. 风格不统一
      2. 计算能力不够
      3. 处理大并发不够好
  3. 企业运行维护很多C/C++的项目,C/C++程序运行速度虽然很快,但是编译速度却很慢,同时还存在内存泄漏的一系列的困扰需要解决
Go的特点

Go语言既保证了达到金泰编译语言的安全和性能,又达到了动态语言开发维护的高效率

  1. 从C语言中继承了很多理念,包括包袋你是语法,控制结构,基础数据类型,调用参数传值,指针等,也保留了和C语言一样的编译执行方式以及弱化的指针
  2. 引入包的概念,用于组织程序结构,Go语言的文件都要归属于一个包,而不能单独存在
  3. 垃圾回收机制,内存自动回收,不需要开发人员管理
  4. 天然并发
    1. 从语言层面支持并发,简单实现
    2. goroutine,轻量级线程,可实现大并发处理,高效利用多核
    3. 基于CPS并发模型(Communicating Sequential Processes)实现
  5. 吸收了管道通信机制,形成Go语言特有的管道channel通过管道chanel,可以实现不同的goroutine之间的相互通信
  6. 函数可以返回多个值
  7. 新的创新:比如切片slice(类似于集合),延时执行defer等
指令

go build [go源码]					# 默认在当前目前编译产生一个'.exe'执行文件
go build -o [目标文件名] [go源码]		# 生成指定文件名的编译文件,注意要带上后缀
go run [go源码]					# 直接编译执行go程序,开发中不建议使用
  • 1
  • 2
  • 3

go buildgo run

  1. go build编译生成的可执行文件可以不依赖go的环境运行
  2. 在编译时,编译器会将程序运行所依赖的库文件包含在可执行文件中
Go语言开发注意事项

  1. Go源文件以’go’为扩展名
  2. Go应用程序的执行入口时main()函数(mian函数所在的包名也必须是main,否则将不是一个执行入口)
  3. Go语言严格区分大小写
  4. Go方法有一条条语句构成,每个语句后面不需要分号(Go语言会在每行后自动加分号);若是多条语句写在同一行中,则可以使用分号将语句分隔开
  5. Go编译器时一行行进行编译的,因此建议一行只写一行语句
  6. Go语言定义的变量或import的包如果没有被使用过,代码不能编译通过
Go中常用的转义字符

  1. \t:制表符
  2. \n:换行
  3. \\:’\’
  4. \":’"’
  5. \r:回车
注释

  1. 行注释//

  2. 块注释/* ... */

  3. 使用细节

    • 对于行注释和块注释,被哦注释的文字,不会被Go编译器执行

      块注释里面不允许有块注释

  4. 格式化代码命令

    1. gofmt [源文件]:输出格式化之后的结果,源文件的后缀不能省略
    2. gofmt -w [源文件]:对源文件进行格式化处理
Go语言中文官方文档
Go基础

变量

  • 变量相当于内存中一个数据存储空间的表示,通过变量名可以访问到变量的值

  • 局部变量

    • var i int
      i = 10
      
      var i = 10
      
      i := 10
      
      var i, j, k = 10, "wuhunyu", 12.12
      
      i, j, k := 10, "wuhunyu", 12.12
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
  • 全局变量

    • var i int
      
      var i = 10
      
      var (
          i = 10
          j = "wuhunyu"
          k = 12.12
      )
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
  • 变量在同一个作用域(在一个函数或者在代码块)内不能重复声明

  • 变量 = 变量名 + 值 + 数据类型

  • 无论是局部变量还是全局变量,都有默认值。当局部变量与全局变量重名时,优先使用本函数或是本代码块中的局部变量

    • 数据类型默认值
      int0
      byte0
      float0
      string“”
      boolfalse

Go中的+与java中的+用法基本一致,当操作数全部为数值类型时为相加,当操作数有一个是字符串时为拼接。但+为相加时,操作必须是相同的数据类型,不存在自动转型

变量的数据类型

  • 基本数据类型

    1. 数值型

      1. 整数类型

        • int,int8,int16,int32,int64

        • unit,uint8,unit16,uint32,unit64,byte

        • 数据类型有无符号占用字节
          int32位系统占4个字节,即相当于int32;64位系统占8个字节,相当于int64
          uint32位系统占4个字节,即相当于uint32;64位系统占8个字节,相当于uint64
          byte等价于uint8,一般用于存储字符,go中没有char类型
          rune基本等价于int32,表示一个Unicode码
      2. 浮点类型

        • float32,float64
    2. 字符型:没有专门的字符型,使用byte来保存单个字母字符,注意go的byte不能保存中文字符

    3. 布尔型(bool):只有true和false两个取值,默认为false

    4. 字符串(string):go中字符串被归属到基本数据类型

  • 派生/复杂数据类型

    1. 指针(Pointer)
    2. 数组
    3. 结构体(struct)
    4. 管道(Channel)
    5. 函数
    6. 切片(slice):类似于List
    7. 接口(interface)
    8. map

查看变量的类型与占用字节

var i = 100
fmt.Printf("type is %T, size is %d", i, unsafe.Sizeof(i))
  • 1
  • 2

浮点数

  • 浮点数 = 符号位 + 指数位 + 尾数位,即浮点数以科学计数法的方式存储
  • 尾数位部分可能丢失,造成精度损失
  • 浮点类型有固定的范围和字段长度,不受具体OS(操作系统)的影响
  • 浮点类型默认声明为float64
  • 通常情况下,应该使用float64,因为它比float32更加精确。但要注意无论是哪一种float,都是会丢失精度的

字符串

字符串就是一串固定长度的字符连接起来的字符序列,Go的字符串是由单个字节连接起来的。也就是说对于传统的字符串是由字符组成的,而Go的字符串不同,他是由字节组成的

一般使用使用ASC码表中的字符,用byte保存即可;如果要保存中文字符,则可以使用rune来保存

var i rune
i = '北'
// 格式化输入字符
fmt.Printf("%c", i)
  • 1
  • 2
  • 3
  • 4

字符常量是用单引号''括起来的单个字符

Go中允许使用转义字符\来将其后的字符转变为特殊字符型常量

Go语言使用的字符集是UTF-8,其中英文占用1个字节,中文占用3个字节

字符本质上是一个整数,直接输出时,是该字符对应的UTF-8编码的码值

字符类型可以与整数类型之间进行运算,字符本身也相当于一个整数

字符保存于读取

  • 存储:字符 -> utf-8码值 -> 二进制

    读取: 二进制 -> utf-8码值 -> 字符

  • 字符和码值的对应关系是通过字符编码表决定好的

  • Go语言的编码都统一成了utf-8

注意事项及细节

字符串一旦赋值了,字符串就不能被修改了,Go中的字符串是不可变的

字符串的两种表示形式

  1. 双引号("),会识别转义字符
  2. 反引号(`),与es6的用法一致,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击,输出源代码等效果

在Go语言中通过+拼接字符串换行时,必须将+写在上一行的结尾。这样Go编译器才会认为这一行还没有结束

  • var str string = "wuhunyu " + "learn " +
    	"Go"
    fmt.Println(str)
    
    • 1
    • 2
    • 3

bool

bool类型的数据只能存储true或者false,默认为false

bool类型的变量占用1个字节

类型转换

Go与许多语言不一样,在不同类型的变量之间赋值时需要显式转换,且Go中不支持数据类型自动转换

// 64位操作系统中go的int占用8个字节,理论上等同于int64
var num1 int = 100
var num2 int64 = 200
// 必须对num1进行类型转换,否则编译不通过
var num3 = int64(num1) + num2
  • 1
  • 2
  • 3
  • 4
  • 5

数据类型的转换可以从表示范围小 -> 表示范围大,也可以是表示范围大 -> 表示范围小

被转换的是变量存储的数据(即数值,非指针),变量本身并不会发生变化

从大范围数据转换成小范围数据时会发生精度丢失

忽略某个包:在包名前加上_

import (
	_ "fmt"
)
  • 1
  • 2
  • 3

其他类型转字符串类型

fmt.Sprintf()

var str string
// int -> string
var num1 int = 123
str = fmt.Sprintf("%d", num1)

// float64 -> string
var num2 float64 = 123.123
str = fmt.Sprintf("%f", num2)

// byte -> string
var num3 byte = 'A'
str = fmt.Sprintf("%c", num3)

// bool -> string
var num4 bool = true
str = fmt.Sprintf("%t", num4)

// string -> string
var num5 string = "wuhunyu"
str = fmt.Sprintf("%s", num5)

// 输出
// %T为数据类型
fmt.Printf("%T", str)

// %V为变量的值,即不进行格式化的值
fmt.Printf("%v", str)

// %q对字符串加上双引号
fmt.Printf("%q", str)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

strconv.FormatInt

  • 参数1:int64的变量

    参数2:需要转换成的进制

strconv.FormatFloat

  • 参数1:float64的变量

    参数2:转换成的格式,如’f’代表小数

    参数3:保留小数位数,即精度

    参数4:转换成的float类型,32或64

strconv.FormatBool

  • bool类型的变量

strconv.Itoa:将int类型转换成string

  • int类型的变量

string类型转换成其他类型

strconv.ParseBool:将string转换成bool类型

  • bool类型的变量

  • var str string
    var flag bool
    flag, _ = strconv.ParseBool(str)
    
    • 1
    • 2
    • 3

strconv.ParseInt:将字符串转换成int64

  • 参数1:string类型变量

    参数2:转换成的进制

    参数3:转换成的类型大小,如8,16,32等,但不是函数返回的类型

  • 注意,函数返回的类型都是int64

strconv.ParseFloat:将字符串类型转换成float64

  • 参数1:string类型变量

    参数2:转换成的类型大小,如32,64,但不是函数返回的类型

  • 注意,函数返回的类型都是float64

注意:若字符串转换成其他类型失败,则会返回该类型的默认值,如int64是0,float64是0,bool是false

指针

基本介绍

  • 基本数据类型,变量存的就是值,也叫值类型

  • 获取变量的地址,使用&

    • var num1 int; fmt.Println(&num1)

  • 指针类型,变量存的是一个地址,这个地址指向的空间才是值

  • var num1 int = 100
    
    var p *int = &num1
    
    // 0xc00000a098
    fmt.Printf("%v\n", p)
    // 100
    fmt.Printf("%v\n", *p)
    // 0xc000006028
    fmt.Printf("%v\n", &p)
    // 0xc00000a098
    fmt.Printf("%v\n", *(&p))
    // 0xc00000a098
    fmt.Printf("%v\n", &(*p))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 结论:p == *(&p) == &(*p)

注意事项

  1. 值类型都有对应的指针类型
  2. 值类型包括:基本数据类型(int系列,float系列,bool,string),数组和结构体struct
  3. 引用类型:指针,slice切片(相当于java中的集合),map,管道chanal,interface等

值类型与引用类型

  1. 值类型
    • 变量直接存储值,内存通常在栈中分配
  2. 引用类型
    • 变量存储的是一个地址,这个地址对应的空间才真正存储数据,内存通常在堆上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就会成为一个垃圾,由GC来回收

关键字注意事项

下划线’_'本身在Go中是一个特殊的标识符,称为空标识符。可以代表任何其他的标识符,但是它对应的值会被忽略(比如忽略某个返回值)。所以仅能被作为占位符使用,不能作为标识符使用

Go中的关键字,如int,int64,bool等可以作为一个普通的变量名来使用,但强烈不建议

标识符命名注意事项

包名与package的名字和目录保持一致,尽量采取有意义的包名,简短,有意义,不要和标准库冲突

变量名,函数名,常量名一般采用驼峰命名

如果变量名,函数名,常量名首字母大写,则可以被其他的包访问

如果首字母小写,则只能在本包中使用

简单理解成,首字母大写是公有的,首字母小写是私有的

Go中的保留关键字

image-20210421225947920

Go中的预定义标识符(用户可使用这些标识符用作变量名,但强烈不建议)

image-20210421230029161

运算符

  1. 算术运算符

    • 注意:Go中的++,--只能独立使用,不能被使用在表达式中,且Go中只有num++,没有++num
  2. 赋值运算符

  3. 比较运算符/关系运算符

  4. 逻辑运算符

  5. 位运算符

    1. 运算符描述实列
      <<=左移后赋值c <<= 2 <==> c = c << 2
      >>=后移后赋值c >>= 2 <==> c = c >> 2
      ^=按位异或后赋值c ^= 2 <==> c = c ^ 2
      &返回变量存储的地址&a给出变量的实际地址
      *指针变量*a是一个指针变量
      &按位与运算同时为1,结果为1,否则为0
      |按位或运算当二进进位不同时,结果为1,否则为0
      <<左移运算左移n位就是乘以2的n次方,符号位不变,低位补0
      >>右移运算右移n位就是乘以2的n次方,低位溢出,符号位不变,并用符号位补溢出的高位
      ^异或运算运算的两个值不相同为1,相同则为0
  6. 其他运算符

  7. 注意:Go中不支持三元运算符

控制台输入函数

fmt.Scanln():读取一行

var name string
var age byte
var sal float64
var isPass bool

fmt.Scanln(&name)
fmt.Scanln(&age)
fmt.Scanln(&sal)
fmt.Scanln(&isPass)

fmt.Println(name, age, sal, isPass)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

fmt.Scanf():格式化输入

var name string
var age byte
var sal float64
var isPass bool

fmt.Scanf("%s %d %f %t", &name, &age, &sal, &isPass)

fmt.Println(name, age, sal, isPass)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
进制

Go中的变量不能直接表示二进制,可以通过格式化得到数的二进制格式

var num1 byte = 5

fmt.Printf("%b",num1)
  • 1
  • 2
  • 3
// 八进制
var num1 byte = 016
// 十六进制,其中x不要求大小写
var num2 byte = 0X1a
  • 1
  • 2
  • 3
  • 4
程序流程控制

分支

Go中的if语句强制要求必须要有{},无论是否只有一行代码

Go的if语言允许在if的条件表达式中声明一个局部变量,但只允许通过:=的方式对局部变量赋值

Go中的else ifelse必须与if}在同一行中

if age := 23; age >= 18 {
    fmt.Println("成年")
} else {
    fmt.Println("未成年")
}
  • 1
  • 2
  • 3
  • 4
  • 5

switch

Go中的switch语句与其他语言的switch语句有较大的区别

  1. case后是一个表达式(即:常量值,变量,一个有返回值的函数等都可以)

  2. case后的各个表达式的值的数据类型必须和switch的表达式类型一致

  3. case后可以带多个表达式,使用逗号间隔,只要满足其中一个表达式则表示通过case

  4. case后面的表达式如果是常量值(字面量),则要求不能重复

  5. case后面不需要break,程序匹配到一个case后就会执行对应的代码块,然后退出switch,如果一个都匹配不到,则执行default(开发者也可以手动加上break)

  6. Go的switch语句支持所有基本类型(包括string)

    • var num1 string = "3"
      
      switch num1 {
          case "1", '2':
          	fmt.Println("1,2")
          case "3", "4":
          	fmt.Println("3,4")
          default:
          	fmt.Println("默认")
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
  7. switch后也可以不带表达式,类似于if-else分支来使用

    • var num1 int = 3
      switch {
          case num1 > 5:
          fmt.Println("num1大于5")
          case num1 <= 5:
          fmt.Println("num1小于等于5")
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
  8. switch后也可以直接声明,定义个变量(必须以分号结尾)

    • switch num1 := 3; {
      case num1 > 5:
      	fmt.Println("num1大于5")
      case num1 <= 5:
      	fmt.Println("num1小于等于5")
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
  9. switch穿透(fallthrough),如果在case语句块后增加fallthrough,这回继续执行下一个case,也叫case穿透,但只能穿透一个case语句块

    • switch num1 := 6; {
      case num1 > 5:
      	fmt.Println("num1大于5")
          // case穿透
      	fallthrough
      case num1 <= 5:
      	fmt.Println("num1小于等于5")
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
  10. Type Switch:switch语句还可以被用于type-switch来判断某个interface变量中实际指向的变量类型

switch和if的比较

  1. 如果判断的具体数值有限,而且符合整数,浮点数,字符,字符串等类型,建议使用switch语句简洁高效
  2. 其他情况,对于区间判断和结果为bool类型的判断,使用if,if的使用范围更广

for语句的注意事项

  1. 循环条件是返回一个布尔值的表达式

  2. for循环的不同写法

    1. // 相当于while循环
      var i int = 1
      for i <= 10 {
          fmt.Println(i)
          i++
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    2. // 死循环,一般需要配合break使用
      var i int = 1
      for {
          fmt.Println(i)
          i++
      }
      
      // 次写法等同于上面的写法
      var i int = 1
      for ; ; {
          fmt.Println(i)
          i++
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

Switch:switch语句还可以被用于type-switch来判断某个interface变量中实际指向的变量类型

switch和if的比较

  1. 如果判断的具体数值有限,而且符合整数,浮点数,字符,字符串等类型,建议使用switch语句简洁高效
  2. 其他情况,对于区间判断和结果为bool类型的判断,使用if,if的使用范围更广

for语句的注意事项

  1. 循环条件是返回一个布尔值的表达式

  2. for循环的不同写法

    1. // 相当于while循环
      var i int = 1
      for i <= 10 {
          fmt.Println(i)
          i++
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    2. // 死循环,一般需要配合break使用
      var i int = 1
      for {
          fmt.Println(i)
          i++
      }
      
      // 次写法等同于上面的写法
      var i int = 1
      for ; ; {
          fmt.Println(i)
          i++
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/850971
推荐阅读
相关标签
  

闽ICP备14008679号