快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

go语言实现字符串合并 go 字符串比较

go语言string之Buffer与Builder

操作字符串离不开字符串的拼接,但是Go中string是只读类型,大量字符串的拼接会造成性能问题。

创新互联是一家集网站建设,磐安企业网站建设,磐安品牌网站建设,网站定制,磐安网站建设报价,网络营销,网络优化,磐安网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

拼接字符串,无外乎四种方式,采用“+”,“fmt.Sprintf()”,"bytes.Buffer","strings.Builder"

上面我们创建10万字符串拼接的测试,可以发现"bytes.Buffer","strings.Builder"的性能最好,约是“+”的1000倍级别。

这是由于string是不可修改的,所以在使用“+”进行拼接字符串,每次都会产生申请空间,拼接,复制等操作,数据量大的情况下非常消耗资源和性能。而采用Buffer等方式,都是预先计算拼接字符串数组的总长度(如果可以知道长度),申请空间,底层是slice数组,可以以append的形式向后进行追加。最后在转换为字符串。这申请了不断申请空间的操作,也减少了空间的使用和拷贝的次数,自然性能也高不少。

bytes.buffer是一个缓冲byte类型的缓冲器存放着都是byte

是一个变长的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一个 空的 buffer,但是可以使用,底层就是一个 []byte, 字节切片。

向Buffer中写数据,可以看出Buffer中有个Grow函数用于对切片进行扩容。

从Buffer中读取数据

strings.Builder的方法和bytes.Buffer的方法的命名几乎一致。

但实现并不一致,Builder的Write方法直接将字符拼接slice数组后。

其没有提供read方法,但提供了strings.Reader方式

Reader 结构:

Buffer:

Builder:

可以看出Buffer和Builder底层都是采用[]byte数组进行装载数据。

先来说说Buffer:

创建好Buffer是一个empty的,off 用于指向读写的尾部。

在写的时候,先判断当前写入字符串长度是否大于Buffer的容量,如果大于就调用grow进行扩容,扩容申请的长度为当前写入字符串的长度。如果当前写入字符串长度小于最小字节长度64,直接创建64长度的[]byte数组。如果申请的长度小于二分之一总容量减去当前字符总长度,说明存在很大一部分被使用但已读,可以将未读的数据滑动到数组头。如果容量不足,扩展2*c + n 。

其String()方法就是将字节数组强转为string

Builder是如何实现的。

Builder采用append的方式向字节数组后添加字符串。

从上面可以看出,[]byte的内存大小也是以倍数进行申请的,初始大小为 0,第一次为大于当前申请的最大 2 的指数,不够进行翻倍.

可以看出如果旧容量小于1024进行翻倍,否则扩展四分之一。(2048 byte 后,申请策略的调整)。

其次String()方法与Buffer的string方法也有明显区别。Buffer的string是一种强转,我们知道在强转的时候是需要进行申请空间,并拷贝的。而Builder只是指针的转换。

这里我们解析一下 *(*string)(unsafe.Pointer(b.buf)) 这个语句的意思。

先来了解下unsafe.Pointer 的用法。

也就是说,unsafe.Pointer 可以转换为任意类型,那么意味着,通过unsafe.Pointer媒介,程序绕过类型系统,进行地址转换而不是拷贝。

即*A = Pointer = *B

就像上面例子一样,将字节数组转为unsafe.Pointer类型,再转为string类型,s和b中内容一样,修改b,s也变了,说明b和s是同一个地址。但是对s重新赋值后,意味着s的地址指向了“WORLD”,它们所使用的内存空间不同了,所以s改变后,b并不会改变。

所以他们的区别就在于 bytes.Buffer 是重新申请了一块空间,存放生成的string变量, 而strings.Builder直接将底层的[]byte转换成了string类型返回了回来,去掉了申请空间的操作。

这个sql语句怎么写?

无论是在sql 2000,还是在 sql 2005 中,都没有提供字符串的聚合函数,

所以,当我们在处理下列要求时,会比较麻烦:

有表tb, 如下:

id value

----- ------

1 aa

1 bb

2 aaa

2 bbb

2 ccc

需要得到结果:

id values

------ -----------

1 aa,bb

2 aaa,bbb,ccc

即, group by id, 求 value 的和(字符串相加)1. 旧的解决方法-- 1. 创建处理函数

CREATE FUNCTION dbo.f_str(@id int)

RETURNS varchar(8000)

AS

BEGIN

DECLARE @r varchar(8000)

SET @r = ''

SELECT @r = @r + ',' + value

FROM tb

WHERE id=@id

RETURN STUFF(@r, 1, 1, '')

END

GO

-- 调用函数SELECt id, values=dbo.f_str(id)

FROM tb

GROUP BY id-- 2. 新的解决方法

-- 示例数据

DECLARE @t TABLE(id int, value varchar(10))

INSERT @t SELECT 1, 'aa'

UNION ALL SELECT 1, 'bb'

UNION ALL SELECT 2, 'aaa'

UNION ALL SELECT 2, 'bbb'

UNION ALL SELECT 2, 'ccc'-- 查询处理

SELECT *

FROM(

SELECT DISTINCT

id

FROM @t

)A

OUTER APPLY(

SELECT

[values]= STUFF(REPLACE(REPLACE(

(

SELECT value FROM @t N

WHERE id = A.id

FOR XML AUTO

), 'N value="', ','), '"/', ''), 1, 1, '')

)N/*--结果

id values

----------- ----------------

1 aa,bb

2 aaa,bbb,ccc

(2 行受影响)

--*/CSDN 社区帖子地址 附: 合并与分拆的CLR, sql2005的示例中有:

在安装sql 2005的示例后,默认安装目录为

drive:\Program Files\Microsoft SQL Server\90\Samples\Engine\Programmability\CLR\StringUtilities中SQL code问题描述:

无论是在sql 2000,还是在 sql 2005 中,都没有提供字符串的聚合函数,

所以,当我们在处理下列要求时,会比较麻烦:

有表tb, 如下:

id value

----- ------

1 aa

1 bb

2 aaa

2 bbb

2 ccc

需要得到结果:

id values

------ -----------

1 aa,bb

2 aaa,bbb,ccc

即, group by id, 求 value 的和(字符串相加)1. 旧的解决方法-- 1. 创建处理函数

CREATE FUNCTION dbo.f_str(@id int)

RETURNS varchar(8000)

AS

BEGIN

DECLARE @r varchar(8000)

SET @r = ''

SELECT @r = @r + ',' + value

FROM tb

WHERE id=@id

RETURN STUFF(@r, 1, 1, '')

END

GO

-- 调用函数SELECt id, values=dbo.f_str(id)

FROM tb

GROUP BY id-- 2. 新的解决方法

-- 示例数据

DECLARE @t TABLE(id int, value varchar(10))

INSERT @t SELECT 1, 'aa'

UNION ALL SELECT 1, 'bb'

UNION ALL SELECT 2, 'aaa'

UNION ALL SELECT 2, 'bbb'

UNION ALL SELECT 2, 'ccc'-- 查询处理

SELECT *

FROM(

SELECT DISTINCT

id

FROM @t

)A

OUTER APPLY(

SELECT

[values]= STUFF(REPLACE(REPLACE(

(

SELECT value FROM @t N

WHERE id = A.id

FOR XML AUTO

), 'N value="', ','), '"/', ''), 1, 1, '')

)N/*--结果

id values

----------- ----------------

1 aa,bb

2 aaa,bbb,ccc

(2 行受影响)

--*/--各种字符串分函数--3.3.1 使用游标法进行字符串合并处理的示例。

--处理的数据

CREATE TABLE tb(col1 varchar(10),col2 int)

INSERT tb SELECT 'a',1

UNION ALL SELECT 'a',2

UNION ALL SELECT 'b',1

UNION ALL SELECT 'b',2

UNION ALL SELECT 'b',3--合并处理

--定义结果集表变量

DECLARE @t TABLE(col1 varchar(10),col2 varchar(100))--定义游标并进行合并处理

DECLARE tb CURSOR LOCAL

FOR

SELECT col1,col2 FROM tb ORDER BY col1,col2

DECLARE @col1_old varchar(10),@col1 varchar(10),@col2 int,@s varchar(100)

OPEN tb

FETCH tb INTO @col1,@col2

SELECT @col1_old=@col1,@s=''

WHILE @@FETCH_STATUS=0

BEGIN

IF @col1=@col1_old

SELECT @s=@s+','+CAST(@col2 as varchar)

ELSE

BEGIN

INSERT @t VALUES(@col1_old,STUFF(@s,1,1,''))

SELECT @s=','+CAST(@col2 as varchar),@col1_old=@col1

END

FETCH tb INTO @col1,@col2

END

INSERT @t VALUES(@col1_old,STUFF(@s,1,1,''))

CLOSE tb

DEALLOCATE tb

--显示结果并删除测试数据

SELECT * FROM @t

DROP TABLE tb

/*--结果

col1 col2

---------- -----------

a 1,2

b 1,2,3

--*/

GO

/*==============================================*/

--3.3.2 使用用户定义函数,配合SELECT处理完成字符串合并处理的示例

--处理的数据

CREATE TABLE tb(col1 varchar(10),col2 int)

INSERT tb SELECT 'a',1

UNION ALL SELECT 'a',2

UNION ALL SELECT 'b',1

UNION ALL SELECT 'b',2

UNION ALL SELECT 'b',3

GO--合并处理函数

CREATE FUNCTION dbo.f_str(@col1 varchar(10))

RETURNS varchar(100)

AS

BEGIN

DECLARE @re varchar(100)

SET @re=''

SELECT @re=@re+','+CAST(col2 as varchar)

FROM tb

WHERE col1=@col1

RETURN(STUFF(@re,1,1,''))

END

GO--调用函数

SELECT col1,col2=dbo.f_str(col1) FROM tb GROUP BY col1

--删除测试

DROP TABLE tb

DROP FUNCTION f_str

/*--结果

col1 col2

---------- -----------

a 1,2

b 1,2,3

--*/

GO/*==============================================*/

--3.3.3 使用临时表实现字符串合并处理的示例

--处理的数据

CREATE TABLE tb(col1 varchar(10),col2 int)

INSERT tb SELECT 'a',1

UNION ALL SELECT 'a',2

UNION ALL SELECT 'b',1

UNION ALL SELECT 'b',2

UNION ALL SELECT 'b',3--合并处理

SELECT col1,col2=CAST(col2 as varchar(100))

INTO #t FROM tb

ORDER BY col1,col2

DECLARE @col1 varchar(10),@col2 varchar(100)

UPDATE #t SET

@col2=CASE WHEN @col1=col1 THEN @col2+','+col2 ELSE col2 END,

@col1=col1,

col2=@col2

SELECT * FROM #t

/*--更新处理后的临时表

col1 col2

---------- -------------

a 1

a 1,2

b 1

b 1,2

b 1,2,3

--*/

--得到最终结果

SELECT col1,col2=MAX(col2) FROM #t GROUP BY col1

/*--结果

col1 col2

---------- -----------

a 1,2

b 1,2,3

--*/

--删除测试

DROP TABLE tb,#t

GO

/*==============================================*/--3.3.4.1 每组 =2 条记录的合并

--处理的数据

CREATE TABLE tb(col1 varchar(10),col2 int)

INSERT tb SELECT 'a',1

UNION ALL SELECT 'a',2

UNION ALL SELECT 'b',1

UNION ALL SELECT 'b',2

UNION ALL SELECT 'c',3--合并处理

SELECT col1,

col2=CAST(MIN(col2) as varchar)

+CASE

WHEN COUNT(*)=1 THEN ''

ELSE ','+CAST(MAX(col2) as varchar)

END

FROM tb

GROUP BY col1

DROP TABLE tb

/*--结果

col1 col2

---------- ----------

a 1,2

b 1,2

c 3

--*/--3.3.4.2 每组 =3 条记录的合并

--处理的数据

CREATE TABLE tb(col1 varchar(10),col2 int)

INSERT tb SELECT 'a',1

UNION ALL SELECT 'a',2

UNION ALL SELECT 'b',1

UNION ALL SELECT 'b',2

UNION ALL SELECT 'b',3

UNION ALL SELECT 'c',3--合并处理

SELECT col1,

col2=CAST(MIN(col2) as varchar)

+CASE

WHEN COUNT(*)=3 THEN ','

+CAST((SELECT col2 FROM tb WHERE col1=a.col1 AND col2 NOT IN(MAX(a.col2),MIN(a.col2))) as varchar)

ELSE ''

END

+CASE

WHEN COUNT(*)=2 THEN ','+CAST(MAX(col2) as varchar)

ELSE ''

END

FROM tb a

GROUP BY col1

DROP TABLE tb

/*--结果

col1 col2

---------- ------------

a 1,2

b 1,2,3

c 3

--*/

GO

if not object_id('A') is null

drop table A

Go

Create table A([id] int,[cname] nvarchar(2))

Insert A

select 1,N'张三' union all

select 2,N'李四' union all

select 3,N'王五' union all

select 4,N'蔡六'

Go

-- -- if not object_id('B') is null

drop table B

Go

Create table B([id] int,[cname] nvarchar(5))

Insert B

select 1,N'1,2,3' union all

select 2,N'3,4'

Go

create function F_str(@cname nvarchar(100))

returns nvarchar(100)

as

begin

select @cname=replace(@cname,ID,[cname]) from A where patindex('%,'+rtrim(ID)+',%',','+@cname+',')0

return @cname

end

go

select [id],dbo.F_str([cname])[cname] from Bid cname

----------- ----------------------------------------------------------------------------------------------------

1 张三,李四,王五

2 王五,蔡六

Go中字符串的遍历

首先说一下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语言中字符串怎么跟变量拼接

你是说 goto 标号? 把标号换成变量?

不好这么做,标号到是可以换成自定义的常量,变量不行

你要非用变量

直接写判断if,然后执行不同的goto不就好了么

话说 goto 还是少用点,多了会乱


当前名称:go语言实现字符串合并 go 字符串比较
浏览路径:http://6mz.cn/article/ddgsghe.html

其他资讯