当前位置: 首页 > news >正文

一个公司可以注册几个网站网络服务商分为哪几类

一个公司可以注册几个网站,网络服务商分为哪几类,智能家居型网站开发,建设手机网银可以自己提升额度吗前面提到过,Go原生支持通过/操作符来连接多个字符串以构造一个更长的字符串,并且通过/操作符的字符串连接构造是最自然、开发体验最好的一种。 但Go还提供了其他一些构造字符串的方法,比如: ● 使用fmt.Sprintf; ● 使…

前面提到过,Go原生支持通过+/+=操作符来连接多个字符串以构造一个更长的字符串,并且通过+/+=操作符的字符串连接构造是最自然、开发体验最好的一种。

但Go还提供了其他一些构造字符串的方法,比如:
● 使用fmt.Sprintf;
● 使用strings.Join;
● 使用strings.Builder;
● 使用bytes.Buffer。
在这些方法中哪种方法最为高效呢?我们使用基准测试的数据作为参考:

var sl []string = []string{
"Rob Pike ",
"Robert Griesemer ",
"Ken Thompson ",
}
func concatStringByOperator(sl []string) string {
var s string
for _, v := range sl {
s += v
}
return s
}
func concatStringBySprintf(sl []string) string {
var s string
for _, v := range sl {
s = fmt.Sprintf("%s%s", s, v)
}
return s
}
func concatStringByJoin(sl []string) string {
return strings.Join(sl, "")
}
func concatStringByStringsBuilder(sl []string) string {
var b strings.Builder
for _, v := range sl {
b.WriteString(v)
}
return b.String()
}
func concatStringByStringsBuilderWithInitSize(sl []string) string {
var b strings.Builder
b.Grow(64)for _, v := range sl {
b.WriteString(v)
}
return b.String()
}
func concatStringByBytesBuffer(sl []string) string {
var b bytes.Buffer
for _, v := range sl {
b.WriteString(v)
}
return b.String()
}
func concatStringByBytesBufferWithInitSize(sl []string) string {
buf := make([]byte, 0, 64)
b := bytes.NewBuffer(buf)
for _, v := range sl {
b.WriteString(v)
}
return b.String()
}
func BenchmarkConcatStringByOperator(b *testing.B) {
for n := 0; n < b.N; n++ {
concatStringByOperator(sl)
}
}
func BenchmarkConcatStringBySprintf(b *testing.B) {
for n := 0; n < b.N; n++ {
concatStringBySprintf(sl)
}
}
func BenchmarkConcatStringByJoin(b *testing.B) {
for n := 0; n < b.N; n++ {
concatStringByJoin(sl)
}
}
func BenchmarkConcatStringByStringsBuilder(b *testing.B) {
for n := 0; n < b.N; n++ {
concatStringByStringsBuilder(sl)
}
}
func BenchmarkConcatStringByStringsBuilderWithInitSize(b *testing.B) {
for n := 0; n < b.N; n++ {
concatStringByStringsBuilderWithInitSize(sl)
}
}
func BenchmarkConcatStringByBytesBuffer(b *testing.B) {
for n := 0; n < b.N; n++ {
concatStringByBytesBuffer(sl)
}
}
func BenchmarkConcatStringByBytesBufferWithInitSize(b *testing.B) {
for n := 0; n < b.N; n++ {
concatStringByBytesBufferWithInitSize(sl)
}
}

运行该基准测试:

$go test -bench=. -benchmem ./string_concat_benchmark_test.go
goos: darwin
goarch: amd64
BenchmarkConcatStringByOperator-8 11744653 89.1 ns/op 80 B/op 2 allocs/op
BenchmarkConcatStringBySprintf-8 2792876 420 ns/op 176 B/op 8 allocs/op
BenchmarkConcatStringByJoin-8 22923051 49.1 ns/op 48 B/op 1 allocs/op
BenchmarkConcatStringByStringsBuilder-8 11347185 96.6 ns/op 112 B/op 3 allocs/op
BenchmarkConcatStringByStringsBuilderWithInitSize-8 26315769 42.3 ns/op 64 B/op 1 allocs/op
BenchmarkConcatStringByBytesBuffer-8 14265033 82.6 ns/op 112 B/op 2 allocs/op
BenchmarkConcatStringByBytesBufferWithInitSize-8 24777525 48.1 ns/op 48 B/op 1 allocs/op
PASS
ok command-line-arguments 8.816s

从基准测试的输出结果的第三列,即每操作耗时的数值来看:

● 做了预初始化的strings.Builder连接构建字符串效率最高;

● 带有预初始化的bytes.Buffer和strings.Join这两种方法效率十分接近,分列二三位;

● 未做预初始化的strings.Builder、bytes.Buffer和操作符连接在第三档次;

● fmt.Sprintf性能最差,排在末尾。

由此可以得出一些结论:

● 在能预估出最终字符串长度的情况下,使用预初始化的strings.Builder连接构建字符串效率最高

● strings.Join连接构建字符串的平均性能最稳定,如果输入的多个字符串是以[]string承载的,那么strings.Join也是不错的选择;

● 使用操作符连接的方式最直观、最自然,在编译器知晓欲连接的字符串个数的情况下,使用此种方式可以得到编译器的优化处理;

● fmt.Sprintf虽然效率不高,但也不是一无是处,如果是由多种不同类型变量来构建特定格式的字符串,那么这种方式还是最适合的。

转换

在前面的例子中,我们看到了string到[]rune以及string到[]byte的转换,这两个转
换也是可逆的,也就是说string和[]rune、[]byte可以双向转换。下面就是从[]rune或
[]byte反向转换为string的例子:

func main() {rs := []rune{0x4E2D,0x56FD,0x6B22,0x8FCE,0x60A8,}s := string(rs)fmt.Println(s)sl := []byte{0xE4, 0xB8, 0xAD,0xE5, 0x9B, 0xBD,0xE6, 0xAC, 0xA2,0xE8, 0xBF, 0x8E,0xE6, 0x82, 0xA8,}s = string(sl)fmt.Println(s)
}
$go run string_slice_to_string.go
中国欢迎您
中国欢迎您

无论是string转slice还是slice转string,转换都是要付出代价的,这些代价的根源
在于string是不可变的,运行时要为转换后的类型分配新内存。我们以byte slice与
string相互转换为例,看看转换过程的内存分配情况:

func byteSliceToString() {
sl := []byte{
0xE4, 0xB8, 0xAD,
0xE5, 0x9B, 0xBD,
0xE6, 0xAC, 0xA2,
0xE8, 0xBF, 0x8E,
0xE6, 0x82, 0xA8,
0xEF, 0xBC, 0x8C,
0xE5, 0x8C, 0x97,
0xE4, 0xBA, 0xAC,
0xE6, 0xAC, 0xA2,
0xE8, 0xBF, 0x8E,0xE6, 0x82, 0xA8,
}
_ = string(sl)
}
func stringToByteSlice() {
s := "中国欢迎您,北京欢迎您"
_ = []byte(s)
}
func main() {
fmt.Println(testing.AllocsPerRun(1, byteSliceToString))
fmt.Println(testing.AllocsPerRun(1, stringToByteSlice))
}

运行这个例子:

$go run string_mallocs_in_convert.go
1
1

我们看到,针对“中国欢迎您,北京欢迎您”这个长度的字符串,在string与byte
slice互转的过程中都要有一次内存分配操作。

在Go运行时层面,字符串与rune slice、byte slice相互转换对应的函数如下:

slicebytetostring: []byte -> string
slicerunetostring: []rune -> string
stringtoslicebyte: string -> []byte
stringtoslicerune: string -> []rune

以byte slice为例,看看slicebytetostring和stringtoslicebyte的实现:

const tmpStringBufSize = 32
type tmpBuf [tmpStringBufSize]byte
func stringtoslicebyte(buf *tmpBuf, s string) []byte {
var b []byte
if buf != nil && len(s) <= len(buf) {
*buf = tmpBuf{}
b = buf[:len(s)]
} else {
b = rawbyteslice(len(s))
}
copy(b, s)
return b
}func slicebytetostring(buf *tmpBuf, b []byte) (str string) {l := len(b)if l == 0 {return ""}// 此处省略一些代码if l == 1 {stringStructOf(&str).str = unsafe.Pointer(&staticbytes[b[0]])stringStructOf(&str).len = 1return}var p unsafe.Pointerif buf != nil && len(b) <= len(buf) {p = unsafe.Pointer(buf)} else {p = mallocgc(uintptr(len(b)), nil, false)}stringStructOf(&str).str = pstringStructOf(&str).len = len(b)memmove(p, (*(*slice)(unsafe.Pointer(&b))).array, uintptr(len(b)))return
}

想要更高效地进行转换,唯一的方法就是减少甚至避免额外的内存分配操作。我们看
到运行时实现转换的函数中已经加入了一些避免每种情况都要分配新内存操作的优化(如
tmpBuf的复用)。
slice类型是不可比较的,而string类型是可比较的,因此在日常Go编码中,我们会经
常遇到将slice临时转换为string的情况。Go编译器为这样的场景提供了优化。在运行时中
有一个名为slicebytetostringtmp的函数就是协助实现这一优化的:

func slicebytetostringtmp(b []byte) string {if raceenabled && len(b) > 0 {racereadrangepc(unsafe.Pointer(&b[0]),uintptr(len(b)),getcallerpc(),funcPC(slicebytetostringtmp))}if msanenabled && len(b) > 0 {msanread(unsafe.Pointer(&b[0]), uintptr(len(b)))}return *(*string)(unsafe.Pointer(&b))
}

该函数的“秘诀”就在于不为string新开辟一块内存,而是直接使用slice的底层存
储。当然使用这个函数的前提是:在原slice被修改后,这个string不能再被使用了。因此
这样的优化是针对以下几个特定场景的。

1)string(b)用在map类型的key中

b := []byte{'k', 'e', 'y'}
m := make(map[string]string)
m[string(b)] = "value"
m[[3]string{string(b), "key1", "key2"}] = "value1"2string(b)用在字符串连接语句中
b := []byte{'t', 'o', 'n', 'y'}
s := "hello " + string(b) + "!"3string(b)用在字符串比较中
s := "tom"
b := []byte{'t', 'o', 'n', 'y'}
if s < string(b) {
...
}

Go编译器对用在for-range循环中的string到[]byte的转换也有优化处理,它不会为
[]byte进行额外的内存分配,而是直接使用string的底层数据。

看下面的例子:

func convert() {
s := "中国欢迎您,北京欢迎您"
sl := []byte(s)
for _, v := range sl {
_ = v
}
}
func convertWithOptimize() {
s := "中国欢迎您,北京欢迎您"
for _, v := range []byte(s) {
_ = v
}
}
func main() {
fmt.Println(testing.AllocsPerRun(1, convert))
fmt.Println(testing.AllocsPerRun(1, convertWithOptimize))
}

运行这个例子程序:

$go run string_for_range_covert_optimize.go
1
0

从结果我们看到,convertWithOptimize函数将string到[]byte的转换放在for-range
循环中,Go编译器对其进行了优化,节省了一次内存分配操作。

http://www.yayakq.cn/news/439338/

相关文章:

  • 宾馆网站建设wordpress网页地址
  • 怎么去除自己做的网站百度销售是做什么
  • 如何做配送网站做信息安全的网站
  • 2_ 如何写一份详细的网站开发方案怎么用wordpress建手机网站
  • 网站其它方面seo情况成都网页编辑器开发
  • 免费网站如何被百度收录如何用dreamer做网站
  • 简洁文章网站模板下载移动开发
  • wordpress插件 网站网站删除期查询
  • 衡阳衡阳县网站建设谷德设计网下载
  • php网站开发技术描述如果网站不备案
  • 2017手机网站建设方案wordpress用户怎么发布文章
  • 创建主题资源网站的学习_你觉得在主题资源建设方面有哪些收获?官网cms
  • 旅游网站建设网站山东省建设执业资格注册管理中心网站
  • 建站长沙密云网站建设公司
  • 怎么做网站的用户注册代写稿子的平台
  • 惠州做网站小程序哪里有未成年做的网站
  • 互联网网站名字建筑网站推荐
  • 搭建网站空间云猎建筑人才网
  • 海外人才招聘网站wordpress弹幕播放器
  • 免费网站流量统计wordpress编辑器添加短代码按钮
  • 做的网站怎样评估价值酒店网站模板设计方案
  • wordpress设置中改网站wordpress图片排列
  • 网站备案在外地二维码生成器免费
  • 关于网站建设的论文题目郑州市城乡建设厅网站
  • 网站建设市场调研报告重庆做网站好的公司
  • 杭州企业seo网站优化开发一个app价格
  • 一般网站开发公司网站蓝色和红色搭配
  • 网站内部链接导向自己设计家装的app
  • 不关站备案wordpress 2019手机在线做ppt的网站
  • 怎么做自己微信的网站做微信平台网站