go的byte跟byte string 区别有什么区别

go中string和slice no-copy转换 - 推酷
go中string和slice no-copy转换
在go里面,string和slice的互换是需要进行内存拷贝的,虽然在底层,它们都只是用 pointer + len来表示的一段内存。
通常,我们不会在意string和slice的转换带来的内存拷贝性能问题,但是总有些地方需要关注的,刚好在看vitess代码的时候,发现了一种很hack的做法,string和slice的转换只需要拷贝底层的指针,而不是内存拷贝。当然这样做的风险各位就要好好担当了:
func String(b []byte) (s string) {
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
pstring.Data = pbytes.Data
pstring.Len = pbytes.Len
func Slice(s string) (b []byte) {
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
pbytes.Data = pstring.Data
pbytes.Len = pstring.Len
pbytes.Cap = pstring.Len
在我的测试例子中,slice转string之后,如果slice的值有变化,string也会跟着改变,如下:
b := []byte(&hello world&)
a := String(b)
b[0] = 'a'
println(a)
aello world
但是string转slice之后,就不能更改slice了,如下:
a := &hello world&
b := Slice(a)
b[0] = 'a'
//这里就等着崩溃吧
//但是可以这样,因为go又重新给b分配了内存
b = append(b, &hello world&…)
上面为什么会崩溃我猜想可能是string是immutable的,可能对应的内存地址也是不允许改动的。
另外,上面这个崩溃在defer里面是recover不回来的,真的就崩溃了,原因可能就跟c的非法内存访问一样,os不跟你玩了。
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致5244人阅读
goLang(8)
Go 语言中包括以下内置基础类型:
布尔型:bool
整型:int int64 int32 int16 int8 uint8(byte) uint16 uint32 uint64 uint
浮点型:float32 float64
复数型:complex64 complex128
字符串:string
字符型:rune
错误型:error
1. bool类型
关键字: bool
可定义为: true 或者 false 或者 逻辑表达式
var bool1 bool = true
var bool2 bool = (2 == 2)注:不能接受其他类型的赋值,包括(0, 1),也不支持自动或强制类型转换
分为有符号与无符号两种
值范围,如: int8 2^8 -128~127, uint8 0~255, 其他以此类推
int/uint 其值范围与平台有关,所以 int32 != int
支持强制类型转换,注意精度问题
变量2 = 类型(变量1)
即含小数点的数据
有两种: float32 float64(默认)
可相互转换,
注:比较大小时最好先确定比较精度, 再比较大小
声明方式: var str string
值用 && 或者 `` 包括, `` 可包含多行字符串
字符串的操作与数组相同
与如php等其他语言不同的是,字符串的内容在初始化后,不能被修改,但可重新完全赋值
s := &123&
s[1] = &3& //compile error$s = &123&; $s[1] = &3&; echo $s; //133
两种字符类型:&
byte 对应 utf-8
rune 对应 unicode
在 go 语言中,负责错误信息处理的是 error 接口,也可以使用 errors 包
var e error = errors.New(&...&)
在 go 语言中,函数支持多个返回值
可用下面的方式来处理错误
res, err := funName(param)
if err != nil {
//处理错误
func funName(param) (res type, err error) {
err = errors.New(...)
return res, nil
在此省略,有需要可再了解
note_type_1.go code list
package main
import &fmt&
import &errors& //引入 errors 包
//声明 bool 型全局变量
enable = true
disable = false
func main() {
//预定义常量 iota
c0 = iota //0
c1 = iota //0+1
//会自动赋上一个定义常量的值或者表达式
c3 = iota //0
fmt.Println(&c0, c1, c2 = &, c0, c1, c2)
fmt.Println(&c3, c4 = &, c3, c4)
//这种写法编译时会报错,需要 if condition { 在同一行代码中
//missing condition in if statement
//enable == true not used
if enable == true
fmt.Println(&error&)
if enable == true {
fmt.Println(&enabled = &, enable)
fmt.Println(&enabled = &, disable)
//编译时会出现以下错误:
// cannot use 1 (type int) as type bool in assignment
enable = 1;
// cannot convert 1 to type bool
// cannot convert 1 (type int) to type bool
// cannot use 1 (type int) as type bool in assignment
enable = bool(1)
a int8 = 1
//invalid operation: a + b (mismatched types int8 and int)
//c := a + b
//需要做类型转换
c := int(a) + b
fmt.Println(&c = a + b = &, c)
//int32 与 int 是两种不同的类型,但是可用强制类型转换
var d int32
// cannot use b (type int) as type int32 in assignment
d = int32(b)
fmt.Println(&d = &, d)
var f1 float32 = 1.23456
fmt.Printf(&f1 = %.3f \n&, f1) //1.235
f2 := 1.111
//compile error: invalid operation: f1 + f2 (mismatched types float32 and float64
//f3 := f1 + f2
b1 := (float64(f1) == f2)//该比较方式不严谨
fmt.Println(&float64(f1) == f2&)
fmt.Println(&float64(f1) != f2&)
//用 && 括起来表示字符串
//字符串的操作与数组一样
var str string = &hello&
fmt.Println(&str = &, str)
fmt.Println(&str[1] = &, str[1])
fmt.Printf(&%c \n&, str[1]) // s[i]取第i+1个字符
//str = &hi&
//compile ok
//str[0] = 'c' //compile error: cannot assign to str[0]
//多行字符串,用 `` 包含
SELECT username, pwd
FROM tb_user
WHERE id = 123456
fmt.Println(str2)
str3 := & world!&
fmt.Println(&str + str3 = &, str + str3)
// s1 + s2, 连接字符串
//len(s)返回字符串的长度
fmt.Printf(&length of str2 = %d \n&, len(str2))
//s[m:n] 返回从m位开始到n结束之间的字符串,m, n可以省略, 此时m为0, n为len(s)
s := &hello&
s = &c& + s[1:]
fmt.Println(s)
fmt.Println(s[:3])
fmt.Println(s[1:3]) //el
fmt.Println(s[:]) //cello
//byte 用 '' 包括字符
//var ch byte = &1& //compile error: cannot use &1& (type string) as type byte in assignment
var ch1 byte = 'a'
fmt.Printf(&ch1 = %c \n&, ch1)
fmt.Println(ch1)
var ch2 rune = 'b'
fmt.Printf(&ch2 = %c \n&, ch2)
fmt.Println(ch2)
err := errors.New(&error1&)
if err != nil {
//错误处理...
fmt.Println(err)
var e1 error
if e1 == nil {
fmt.Println(&no problem&)
res, e := div(5, 0)
//res, e := div(5, 1)
if e != nil {
//错误处理
fmt.Println(e) //如果div(5, 0), 会输出: error: division by zero
fmt.Println(&res = &, res) //如果div(5, 1),会输出: res = 5
//定义函数
func div(a, b int) (res int, e error) {
if b == 0 {
e = errors.New(&error: division by zero&)
return a /b , nil
运行结果:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:152608次
积分:2097
积分:2097
排名:第12094名
原创:47篇
转载:22篇
评论:14条
(2)(7)(1)(1)(2)(3)(1)(2)(1)(1)(3)(14)(11)(20)Go语言按字节截取字符串的方法
本文实例讲述了Go语言按字节截取字符串的方法。分享给大家供大家参考。具体实现方法如下:
代码如下:// 按字节截取字符串 utf-8不乱码
func SubstrByByte(str string, length int) string {
&&& bs := []byte(str)[:length]
&&& bl := 0
&&& for i:=len(bs)-1; i&=0; i-- {
&&&&&&& switch {
&&&&&&& case bs[i] &= 0 && bs[i] &= 127:
&&&&&&&&&&& return string(bs[:i+1])
&&&&&&& case bs[i] &= 128 && bs[i] &= 191:
&&&&&&&&&&& bl++;
&&&&&&& case bs[i] &= 192 && bs[i] &= 253:
&&&&&&&&&&& cl := 0
&&&&&&&&&&& switch {
&&&&&&&&&&& case bs[i] & 252 == 252:
&&&&&&&&&&&&&&& cl = 6
&&&&&&&&&&& case bs[i] & 248 == 248:
&&&&&&&&&&&&&&& cl = 5
&&&&&&&&&&& case bs[i] & 240 == 240:
&&&&&&&&&&&&&&& cl = 4
&&&&&&&&&&& case bs[i] & 224 == 224:
&&&&&&&&&&&&&&& cl = 3
&&&&&&&&&&& default:
&&&&&&&&&&&&&&& cl = 2
&&&&&&&&&&& }
&&&&&&&&&&& if bl+1 == cl {
&&&&&&&&&&&&&&& return string(bs[:i+cl])
&&&&&&&&&&& }
&&&&&&&&&&& return string(bs[:i])
&&& return ""
希望本文所述对大家的Go语言程序设计有所帮助。
顶一下(0) 踩一下(0)
热门标签:Golang Array 数组 和 Slice 切片
一 数组简介
数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值。在初始化后长度是固定的,无法修改其长度。当作为方法的参数传入时将复制一份数组而不是引用同一指针。数组的长度也是其类型的一部分,通过内置函数len(array)获取其长度。
注意:和C中的数组相比,又是有一些不同的
1. Go中的数组是值类型,换句话说,如果你将一个数组赋值给另外一个数组,那么,实际上就是将整个数组拷贝一份
2. 如果Go中的数组作为函数的参数,那么实际传递的参数是一份数组的拷贝,而不是数组的指针。这个和C要区分开。因此,在Go中如果将数组作为函数的参数传递的话,那效率就肯定没有传递指针高了。
3. array的长度也是Type的一部分,这样就说明[10]int和[20]int是不一样的。array的结构用图示表示是这样的:
len表示数组的长度,后面的int储存的是实际数据
二 数组初始化
初始化数组的初始化有多种形式,查看示例代码
[5] int {1,2,3,4,5}
长度为5的数组,其元素值依次为:1,2,3,4,5
[5] int {1,2}
长度为5的数组,其元素值依次为:1,2,0,0,0 。在初始化时没有指定初值的元素将会赋值为其元素类型int的默认值0,string的默认值是""
[...] int {1,2,3,4,5}
长度为5的数组,其长度是根据初始化时指定的元素个数决定的
[5] int { 2:1,3:2,4:3}
长度为5的数组,key:value,其元素值依次为:0,0,1,2,3。在初始化时指定了2,3,4索引中对应的值:1,2,3
[...] int {2:1,4:3}
长度为5的数组,起元素值依次为:0,0,1,0,3。由于指定了最大索引4对应的值3,根据初始化的元素个数确定其长度为5赋值与使用
三 数组的访问
数组通过下标访问元素,可修改其元素值
arr :=[...] int {1,2,3,4,5}
arr[4]=arr[1]+len(arr)
//arr[4]=2+5
通过for遍历数组元素
arr := [5]int{5, 4, 3}
for index, value := range arr {
fmt.Printf("arr[%d]=%d \n", index, value)
for index := 0; index < len(arr); index&#43;&#43; {
fmt.Printf("arr[%d]=%d \n", index, arr[index])
数组是&#20540;类型,将一个数组赋&#20540;给另一个数组时将复制一份新的元素
arr2 := [5]int{1, 2}
arr5 := arr2
arr5[0] = 5
arr2[4] = 2
fmt.Printf(" arr5= %d \n arr2=%d \n arr5[0]==arr2[0]= %s \n", arr5, arr2, arr5[0] == arr2[0])
arr5=[5 2 0 0 0]
arr2=[1 2 0 0 2]
arr5[0]==arr2[0]= false
四 切片简介
数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型Slices切片(“动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。切片中有两个概念:一是len长度,二是cap容量,长度是指已经被赋过&#20540;的最大下标&#43;1,可通过内置函数len()获得。容量是指切片目前可容纳的最多元素个数,可通过内置函数cap()获得。切片是引用类型,因此在当传递切片时将引用同一指针,修改&#20540;将会影响其他的对象。
五 切片的使用
Slice并不是真正意义上的动态数组,而是一个引用类型。slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。
// 和声明array一样,只是少了长度
var fslice []int
接下来我们可以声明一个slice,并初始化数据,如下所示:
slice := []byte {'a', 'b', 'c', 'd'}
slice可以从一个数组或一个已经存在的slice中再次声明。slice通过array[i:j]来获取,其中i是数组的开始位置,j是结束位置,但不包含array[j],它的长度是j-i。
// 声明一个含有10个元素元素类型为byte的数组
var ar = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// 声明两个含有byte的slice
var a, b []byte
// a指向数组的第3个元素开始,并到第五个元素结束,
a = ar[2:5]
//现在a含有的元素: ar[2]、ar[3]和ar[4]
// b是数组ar的另一个slice
b = ar[3:5]
// b的元素是:ar[3]和ar[4]
注意slice和数组在声明时的区别:声明数组时,方括号内写明了数组的长度或使用...自动计算长度,而声明slice时,方括号内没有任何字符。
它们的数据结构如下所示
slice有一些简便的操作
slice的默认开始位置是0,ar[:n]等价于ar[0:n]slice的第二个序列默认是数组的长度,ar[n:]等价于ar[n:len(ar)]如果从一个数组里面直接获取slice,可以这样ar[:],因为默认第一个序列是0,第二个是数组的长度,即等价于ar[0:len(ar)]
下面这个例子展示了更多关于slice的操作:
// 声明一个数组
var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// 声明两个slice
var aSlice, bSlice []byte
// 演示一些简便操作
aSlice = array[:3] // 等价于aSlice = array[0:3] aSlice包含元素: a,b,c
aSlice = array[5:] // 等价于aSlice = array[5:10] aSlice包含元素: f,g,h,i,j
aSlice = array[:]
// 等价于aSlice = array[0:10] 这样aSlice包含了全部的元素
// 从slice中获取slice
aSlice = array[3:7]
// aSlice包含元素: d,e,f,g,len=4,cap=7
bSlice = aSlice[1:3] // bSlice 包含aSlice[1], aSlice[2] 也就是含有: e,f
bSlice = aSlice[:3]
// bSlice 包含 aSlice[0], aSlice[1], aSlice[2] 也就是含有: d,e,f
bSlice = aSlice[0:5] // 对slice的slice可以在cap范围内扩展,此时bSlice包含:d,e,f,g,h
bSlice = aSlice[:]
// bSlice包含所有aSlice的元素: d,e,f,g
slice是引用类型,所以当引用改变其中元素的&#20540;时,其它的所有引用都会改变该&#20540;,例如上面的aSlice和bSlice,如果修改了aSlice中元素的&#20540;,那么bSlice相对应的&#20540;也会改变。
从概念上面来说slice像一个结构体,这个结构体包含了三个元素:
一个指针,指向数组中slice指定的开始位置长度,即slice的长度
最大长度,也就是slice开始位置到数组的最后位置的长度
Array_a := [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
Slice_a := Array_a[2:5]
上面代码的真正存储结构如下图所示
对于slice有几个有用的内置函数:vcD4KPHVsPgo8bGk+PGNvZGU+bGVuPC9jb2RlPiC78cihPGNvZGU+c2xpY2U8L2NvZGU+tcSzpLbIPGxpPjxjb2RlPmNhcDwvY29kZT4gu/HIoTxjb2RlPnNsaWNlPC9jb2RlPrXE1+6088jdwb88bGk+PGNvZGU+YXBwZW5kPC9jb2RlPiDP8jxjb2RlPnNsaWNlPC9jb2RlPsDvw+bXt7zT0ru49rvy1d+24Lj21KrL2KOsyLu687e1u9jSu7j2us08Y29kZT5zbGljZTwvY29kZT7Su9H5wODQzbXEPGNvZGU+c2xpY2U8L2NvZGU+PGxpPjxjb2RlPmNvcHk8L2NvZGU+ILqvyv08Y29kZT5jb3B5PC9jb2RlPrTT1LQ8Y29kZT5zbGljZTwvY29kZT61xDxjb2RlPnNyYzwvY29kZT7W0Li01sbUqsvYtb3Ev7HqPGNvZGU+ZHN0PC9jb2RlPqOssqLH0re1u9i4tNbGtcTUqsvYtcS49sr9CgrXoqO6PGNvZGU+YXBwZW5kPC9jb2RlPrqvyv274bjEseQ8Y29kZT5zbGljZTwvY29kZT7L+dL908O1xMr91+m1xMTayN2jrLTTtvjTsM/stb3S/dPDzazSu8r91+m1xMbky/w8Y29kZT5zbGljZTwvY29kZT6howogtau1sTxjb2RlPnNsaWNlPC9jb2RlPtbQw7vT0Mqj0+C/1bzko6i8tDxjb2RlPihjYXAtbGVuKQogPT0gMDwvY29kZT6jqcqxo6y0y8qxvau2r8yst9bF5NDCtcTK/dfpv9W85KGjt7W72LXEPGNvZGU+c2xpY2U8L2NvZGU+yv3X6da41eu9q9a4z/LV4rj2v9W85KOstvjUrcr91+m1xMTayN29q7Gjs9ayu7Hko7vG5Mv80v3Tw7TLyv3X6bXEPGNvZGU+c2xpY2U8L2NvZGU+1PKyu8rc07DP7KGjILP1yry7r8fQxqy/ydLUzai5/cr91+nAtLP1yry7r6Os0rK/ydLUzai5/cTa1sO6r8r9bWFrZSgps/XKvLuvCiAus/XKvLuvyrFsZW49Y2FwLNTa17e809Sqy9jKscjnufvI3cG/Y2FwsrvX48qxvauwtGxlbrXEMrG2wKnI3SCy6b+0yr7A/bT6wuujrNTaz9/Uy9DQyr7A/bT6wus8YnI+Cjxicj4Kwfkgs6PTw7XEs/XKvLuvt723qKO6CgogICAgICAgcyA6PVtdIGludCB7MSwyLDMgfTxicj4K1rG907P1yry7r8fQxqyjrFtdse3KvsrHx9DGrMDg0M2jrHsxLDIsM32z9cq8u68mIzIwNTQwO9LAtM7KxzEsMiwzLsbkY2FwPWxlbj0zPGJyPgogICAgIAoKICAgICAgIHMgOj0gYXJyWzpdPGJyPgqz9cq8u6/H0MascyzKx8r91+lhcnK1xNL908M8YnI+CiAgICAgCgogICAgICBzIDo9IGFycltzdGFydEluZGV4OmVuZEluZGV4XTxicj4KvathcnLW0LTTz8Kx6nN0YXJ0SW5kZXi1vWVuZEluZGV4LTEgz8K1xNSqy9i0tL2ozqrSu7j20MK1xMfQxqw8YnI+CiAgICAgCgogICAgICBzIDo9IGFycltzdGFydEluZGV4Ol08YnI+CsixyqFlbmRJbmRleMqxvaux7cq+0rvWsbW9YXJytcTX7rrz0ru49tSqy9g8YnI+CiAgICAgCgogICAgIHMgOj0gYXJyWzplbmRJbmRleF08YnI+CsixyqFzdGFydEluZGV4yrG9q7Htyr6002FycrXEtdrSu7j21KrL2L+qyrw8YnI+CiAgICAgCgogICBzMSA6PSBzW3N0YXJ0SW5kZXg6ZW5kSW5kZXhdPGJyPgrNqLn9x9DGrHOz9cq8u6/H0MasczE8YnI+CiAgIAoKICAgIHMgOj1tYWtlKFtdaW50LGxlbixjYXApCgrNqLn9xNrWw7qvyv1tYWtlKCmz9cq8u6/H0MascyxbXWludCCx6sq2zqrG5NSqy9jA4NDNzqppbnS1xMfQxqw8YnI+Cjxicj4KuLMmIzIwNTQwO9PryrnTw8fQxqzKx9L908PA4NDNo6zU2sq508PKsdDo0qrXotLixuSy2df3oaPH0Masv8nS1M2ouf3E2tbDuq/K/WFwcGVuZChzbGljZSBbXVR5cGUsZWxlbXMgLi4uVHlwZSnXt7zT1KrL2KOsZWxlbXO/ydLUysfSu8XFdHlwZcDg0M21xMr9vt2jrNKyv8nS1MrHc2xpY2Us0vLOqte3vNO1xNK7uPbSu7j2tcTUqsvYo6zS8rTLyOe5+72r0ru49nNsaWNl17e807W9we3Su7j2c2xpY2XW0NDo0qq0+MnP"...",这样才能表示是将slice中的元素依次追加到另一个slice中。另外在通过下标访问元素时下标不能超过len大小,如同数组的下标不能超出len范围一样。
s :=append(s,1,2,3,4)
s :=append(s,s1…)
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 bytestring是什么类型 的文章

 

随机推荐