189 8069 5689

go语言safemap go语言教程

如何看待go语言泛型的最新设计?

Go 由于不支持泛型而臭名昭著,但最近棚基,泛型已接近成为现实。Go 团队实施了一个看起来比较稳定的设计草案,并且正以源到源翻译器原型的形式获得关注。本文讲述的是泛型的最新设计,以及如何自己尝试泛型。

越城网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设公司等网站项目制作,到程序开发,运营维护。创新互联从2013年开始到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联

例子

FIFO Stack

假设你要创建一个先进先出堆栈。没有泛型,你可能会这样实现:

type Stack []interface{}func (s Stack) 橘和销Peek() interface{} {

return s[len(s)-1]

}

func (s *Stack) Pop() {

*s = (*s)[:

len(*s)-1]

}

func (s *Stack) Push(value interface{}) {

*s = 

append(*s, value)

}

但是,这里存在一个问题:每当你 Peek 项时,都必须使用类型断言将其从 interface{} 转换为你需要的类型。如果你的堆栈是 *MyObject 的堆栈,则意味着很多 s.Peek().(*MyObject)这样的代码。这不仅让人眼花缭乱,而且还可能引发错误。比如忘记 * 怎么办?或者如果您输入错误的类型怎么办?s.Push(MyObject{})` 可以顺利编译,而且你可能不会发现到自己的错误,直到它影响到你的整个服务为止。

通常,使用 interface{} 是相对危险的。使用更多受限制的类型总是更安全,因为可以在编译时而不是运行时发现问题。

泛型通过允许类型具有类型参数来解决此问题:

type Stack(type T) []Tfunc (s Stack(T)) Peek() T {

return s[len(s)-1]

}

func (s *Stack(T)) Pop() {

*s = (*s)[:

len(*s)-1]

}

func (s *Stack(T)) Push(value T) {

*s = 

append(*s, value)

}

这会向 Stack 添加一个类型参数,从而完全不需要 interface{}。现在,当你使用 Peek() 时,返回的值已经是原始类型,并且没有机会返回错误的值类型。这种方式更安全,更容易使用。(译注:就是看起来更丑陋,^-^)

此外,泛型代码通常更易于编译器优化,从而获得更好的性能(以二进制大小为代价)。如果我们对上面的非泛型代码和泛型代码进行基准测试,我们可以看到区别:

type MyObject struct {

int

}

var sink MyObjectfunc BenchmarkGo1(b *testing.B) {

for i := 0; i  b.N; i++ {

var s Stack

s.Push(MyObject{})

s.Push(MyObject{})

s.Pop()

sink = s.Peek().(MyObject)

}

}

func BenchmarkGo2(b *testing.B) {

for i := 0; i  b.N; i++ {

var s Stack(MyObject)

s.Push(MyObject{})

s.Push(MyObject{})

s.Pop()

sink = s.Peek()

}

}

结果:

BenchmarkGo1BenchmarkGo1-16     12837528         87.0 ns/op       48 B/op        2 allocs/opBenchmarkGo2BenchmarkGo2-16     28406479         41.9 ns/op       24 B/op        2 allocs/op

在这种情况下,我们分配更少圆游的内存,同时泛型的速度是非泛型的两倍。

合约(Contracts)

上面的堆栈示例适用于任何类型。但是,在许多情况下,你需要编写仅适用于具有某些特征的类型的代码。例如,你可能希望堆栈要求类型实现 String() 函数

golang 字符串转map?

您可以使用猛备 Go 语言的 "strings" 包中的 "Split" 函数将字符串拆分为键值对,者轿然后使用 "map" 数据类型存储这些键值枝嫌毁对。

下面是代码示例:

package main

import (

"fmt"

"strings"

)

func main() {

str := "frame= 425 fps= 71 q=-1.0 Lsize= 5158kB time=00:00:17.11 bitrate=2468.7kbits/s dup=1 drop=0 speed=2.84x"

m := make(map[string]string)

pairs := strings.Split(str, " ")

for _, pair := range pairs {

kv := strings.Split(pair, "=")

if len(kv) == 2 {

m[kv[0]] = kv[1]

}

}

fmt.Println(m)

}

运行上述代码后,您将得到一个存储字符串中的键值对的 "map" 对象。如果键值对不存在,则不会将它们存储到 "map" 中。

Go语言map是怎么比较key是否存在的

首先,不推荐使用[]来判断key是否存在,因为使用操作符[]会向map容器里插入一个元素.map的operator[]重载大致是这样一个内容:

data_type operator[]( const key_type k ){value_type v(k,data_type());

iterator it = insert(v).first;

} 大致是这样,如果没有找到的话就插入一个,然后返回它的second.正确的判断源碧困方法是使用map的find函数,由于map是一雹念个红黑树,find的时间复杂慧冲度是logn,可以接受.bool i***ist(constString keyName) { return( mRegistryMap.find(keyName)!= mRegistryMap.end()); }


本文标题:go语言safemap go语言教程
文章地址:http://cdxtjz.cn/article/dsppsoh.html

其他资讯