如何在golang中动态更改类型定义?

时间:2018-03-09 10:16:38

标签: go typedef

我遇到过一个场景,我必须使用一个变量来计算,比方说255或65535(取决于一个标志)并溢出到0.所以当我设置标志为say,true时,类型定义应该是uint8,当为false时,类型定义应该是uint16。显然我可以将主变量设置为uint16并对它们执行数学操作,但是有没有本机解决方案呢?

1 个答案:

答案 0 :(得分:3)

Go是一种静态类型语言,这意味着必须在编译时知道变量类型,并且不能在运行时更改它们的类型。

带结构的计数器

而是使用负责增加其值的方法创建自己的counter类型,这可以检查是否超出了计数器的最大值,在这种情况下它可以重置它。

type Counter struct {
    value, Max int
}

func (c *Counter) Inc() {
    c.value++
    if c.value > c.Max {
        c.value = 0
    }
}

func (c *Counter) Value() int { return c.value }

使用它的示例:

c := &Counter{Max: 255}

for i := 0; i < 257; i++ {
    c.Inc()
    if i > 252 {
        fmt.Println(c.Value())
    }
}

输出(在Go Playground上尝试):

254
255
0
1

所以在你的情况下使用它:

c := &Counter{}
if flagUse8bit {
    c.Max = 0xff
} else {
    c.Max = 0xffff
}

带接口的计数器

另一个不错的解决方案是使用接口,因为接口类型的变量可以保存实现该接口的任何类型的值。

创建Counter接口类型:

type Counter interface {
    Inc()
    Value() int
}

对于不同的类型有不同的实现,只需使用不同的底层类型,利用溢出将自然发生的事实。您可以根据CLI标志值选择要存储在Counter接口变量中的运行时类型。

type counter8 uint8

func (c *counter8) Inc()      { *c++ }
func (c counter8) Value() int { return int(c) }

type counter16 uint16

func (c *counter16) Inc()      { *c++ }
func (c counter16) Value() int { return int(c) }

使用它:

var c Counter

c = new(counter8)
for i := 0; i < 257; i++ {
    c.Inc()
    if i > 252 {
        fmt.Println(c.Value())
    }
}

c = new(counter16)
for i := 0; i < 65537; i++ {
    c.Inc()
    if i > 65532 {
        fmt.Println(c.Value())
    }
}

输出(在Go Playground上尝试):

254
255
0
1
65534
65535
0
1

所以在你的情况下使用它:

var c Counter
if flagUse8bit {
    c = new(counter8)
} else {
    c = new(counter16)
}