大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
Go中的binary包实现了简单的数字与字节序列的转换以及变长值的编解码
创新互联公司专注于台江网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供台江营销型网站建设,台江网站制作、台江网页设计、台江网站官网定制、微信小程序服务,打造台江网络公司原创品牌,更为您提供台江网站排名全网营销落地服务。
package main
import ( "fmt" "bytes" "encoding/binary" ) func main(){ n := 0x12345678 bytesBuffer := bytes.NewBuffer([]byte{}) //BigEndian 大端顺序存储 LittleEndian小端顺序存储 binary.Write(bytesBuffer, binary.BigEndian, int32(n)) data:=bytesBuffer.Bytes() fmt.Printf("[0]: %#x addr:%#x\n",data[0],data[0]) fmt.Printf("[0]: %#x addr:%#x\n",data[1],data[1]) fmt.Printf("[0]: %#x addr:%#x\n",data[2],data[2]) fmt.Printf("[0]: %#x addr:%#x\n",data[3],data[3]) }
输出
[0]: 0x12 addr:0xc042010248 [1]: 0x34 addr:0xc042010249 [2]: 0x56 addr:0xc04201024a [3]: 0x78 addr:0xc04201024b
也可以使用下面的方式
n := 0x12345678 var data []byte = make([]byte,4) //操作的都是无符号整型 binary.BigEndian.PutUint32(data,uint32(n))
可以使用下面的方式判断当前系统的字节序类型
const INT_SIZE int = int(unsafe.Sizeof(0))
//判断我们系统中的字节序类型 func systemEdian() { var i int = 0x1 bs := (*[INT_SIZE]byte)(unsafe.Pointer(i)) if bs[0] == 0 { fmt.Println("system edian is little endian") } else { fmt.Println("system edian is big endian") } }
包 utf-8 实现的功能和常量用于文章utf8编码,包含runes和utf8字节序列的转换功能.在unicode中,一个中文占两个字节,utf-8中一个中文占三个字节,golang默认的编码是utf-8编码,因此默认一个中文占三个字节,但是golang中的字符串底层实际上是一个byte数组.
Output:
RuneSelf该值的字节码值为128,在判断是否是常规的ascii码是使用。hicb字节码值为191. FF 的对应的字节码为255。
计算字符串中的rune数量,原理:首先取出字符串的码值,然后判断是不是个小于128的,如果是小于则直接continue.rune个数++.
如果是个十六进制f1.的则是无效字符,直接continue.rune个数++,也就是说一个无效的字符也当成一个字长为1的rune.如果字符的码值在first列表中的值和7按位的结果为其字长,比如上面示例中的 钢 。其字长为三位,第一位的值为 233 .二进制形式为 11101001 ;与7按位与后的值为0.从acceptRanges中取出的结果为{locb, hicb}。也就是标识 ox80 到 0xbf 之间的值。而结果n也就是直接size+3跳过3个字节后,rune个数++。其他函数的处理流程差不多,不再过多叙述。
示例:
ValidString返回值表明参数字符串是否是一个合法的可utf8编码的字符串。
RuneCount返回参数中包含的rune数量,第一个例子中将 utf8.RuneCountInString ,改成该方法调用,返回的结果相同。错误的和短的被当成一个长一字节的rune.单个字符 H 就表示一个长度为1字节的rune.
该函数标识参数是否以一个可编码的rune开头,上面的例子中,因为字符串是以一个ascii码值在0-127内的字符开头,所以在执行
first[p[0]] 时,取到的是 p[0] 是72,在first列表中,127之前的值都相同都为 0xF0 ,十进制标识为240,与7按位与后值为0,所以,直接返回 true .
和FullRune类似,只是参数为字符串形式
首先说一下go中的字符串类型:
字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本。
下面介绍字符串的三种遍历方式,根据实际情况选择即可。
该遍历方式==缺点==:遍历是按照字节遍历,因此如果有中文等非英文字符,就会出现乱码,比如要遍历"abc北京"这个字符串,效果如下:
可见这不是我们想要的效果,根据utf-8中文编码规则,我们要str[3]str[4]str[5]三个字节合起来组成“北”字及 str[6]str[7]str[8]合起来组成“京”字。由此引出下面第二种遍历方法。
该方式是按照字符遍历的,所以不会出现乱码,如下:
运行结果:
从图中可以看到第二个汉子“京”的开始下标是6,直接跳过了4和5,可见确实依照utf8编码方式将三个字节组合成了一个汉字,str[3]-str[5]组合成“北”字,str[6]-str[8]组合成了“京”字。
由于下标的不确定性,所以引出了下面的遍历方式。
1 可以先将字符串转成 []rune 切片
2 再用常规方法进行遍历
运行效果:
由此可见下标是按1递增的,没有产生跳跃现象。
Go语言标准库中提供了sort包对整型,浮点型,字符串型切片进行排序,检查一个切片是否排好序,使用二分法搜索函数在一个有序切片中搜索一个元素等功能。
关于sort包内的函数说明与使用,请查看
在这里简单讲几个sort包中常用的函数
在Go语言中,对字符串的排序都是按照字节排序,也就是说在对字符串排序时是区分大小写的。
二分搜索算法
Go语言中提供了一个使用二分搜索算法的sort.Search(size,fn)方法:每次只需要比较㏒₂n个元素,其中n为切片中元素的总数。
sort.Search(size,fn)函数接受两个参数:所处理的切片的长度和一个将目标元素与有序切片的元素相比较的函数,该函数是一个闭包,如果该有序切片是升序排列,那么在判断时使用 有序切片的元素 = 目标元素。该函数返回一个int值,表示与目标元素相同的切片元素的索引。
在切片中查找出某个与目标字符串相同的元素索引
Buffer 介绍
Buffer 是 bytes 包中的一个 type Buffer struct{…}
A buffer is a variable-sized buffer of bytes with Read and Write methods. The zero value for Buffer is an empty buffer ready to use.
(是一个变长的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一个 空的 buffer,但是可以使用)
Buffer 就像一个集装箱容器,可以存东西,取东西(存取数据)
创建缓冲器
输出
写入到缓冲器
buffer在new的时候是空的,也是可以直接Write的
Write
结果
WriteString
结果
WriteByte
WriteRune
结果
从缓冲器中写出
读出缓冲器
Read
ReadByte
返回缓冲器头部的第一个byte
ReadRun
ReadRune方法,返回缓冲器头部的第一个rune
为什么n==3,而n1==1呢?我们看下ReadRune 的源码
ReadBytes
ReadBytes方法,需要一个byte作为分隔符,读的时候从缓冲器里找出第一个出现的分隔符,缓冲器头部开始到分隔符之间的byte返回。
相当于有一个分隔符
ReadString
和readBytes方法类似
读入缓冲器
ReadFrom方法,从一个实现io.Reader接口的r,把r的内容读到缓冲器里,n返回读的数量
从缓冲器取出
Next方法,返回前n个byte(slice),原缓冲器变
缓冲区原理介绍
go字节缓冲区底层以字节切片做存储,切片存在长度len与容量cap, 缓冲区写从长度len的位置开始写,当lencap时,会自动扩容。缓冲区读会从内置标记off位置开始读(off始终记录读的起始位置),当off==len时,表明缓冲区已全部读完
并重置缓冲区(len=off=0),此外当将要内容长度+已写的长度(即len) = cap/2时,缓冲区前移覆盖掉已读的内容(off=0,len-=off),从避免缓冲区不断扩容
int is a signed integer type that is at least 32 bits in size. It is a distinct type, however, and not an alias for, say, int32.
int 是带符号整数类型,其大小至少为32位。 它是一种确切的类型,而不是 int32 的别名。
int 不是int32,那 int 在内存站多少字节呢?官方没有明确,让我们测试下。
GOARCH="amd64"
package main
import (
"fmt"
"unsafe"
)
func main() {
i := int(1)
fmt.Println(unsafe.Sizeof(i)) // 4
j := 1
fmt.Println(unsafe.Sizeof(j)) // 4
u := uint(1)
fmt.Println(unsafe.Sizeof(u)) // 4
}
可以认为 int 是4字节么?我不敢这样认为,GoLang支持多种平台架构。如果对size有明确要求,那就用 int32 之类的吧。
补充:随Go版本的变化,这个的确是在变化,所以到底占用多少字节,还是看具体版本吧