首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >go中的类型转换问题

go中的类型转换问题
EN

Stack Overflow用户
提问于 2012-11-11 23:50:45
回答 3查看 235关注 0票数 0

如何重写下面的代码?

代码语言:javascript
运行
复制
switch md.(type) {
    case *amf0.EcmaArrayType:
        ea := md.(*amf0.EcmaArrayType)
        for k, v := range (*ea) {
            log.Printf("%v = %v\n", k, v)
        }
        if width == 0 {width = uint16((*ea)["width"].(amf0.NumberType))}
        if height == 0 {height = uint16((*ea)["height"].(amf0.NumberType))}
    case *amf0.ObjectType:
        ea := md.(*amf0.ObjectType)
        for k, v := range (*ea) {
            log.Printf("%v = %v\n", k, v)
        }
        if width == 0 {width = uint16((*ea)["width"].(amf0.NumberType))}
        if height == 0 {height = uint16((*ea)["height"].(amf0.NumberType))}
}

它有两个完全重复的块,用于不同的类型。如果我在切换状态之上声明了var ea interface{},那么由于编译错误,我不能调用range (*ea)

EN

回答 3

Stack Overflow用户

发布于 2012-11-12 02:55:10

看起来这两种类型都有底层类型map[string]something,其中"something“有一个具体的amf0.NumberType类型。您所做的每个操作都可以使用反射来模拟。

代码语言:javascript
运行
复制
switch md.(type) {
case *amf0.EcmaArrayType, *amf0.ObjectType:
    m := reflect.Indirect(reflect.ValueOf(md))
    for _, key := range m.MapKeys() {
        k, v := key.Interface(), m.MapIndex(key).Interface()
        log.Printf("%v = %v\n", k, v)
    }

    if width == 0 {
        w := m.MapIndex(reflect.ValueOf("width"))
        width = uint16(w.Interface().(amf0.NumberType))
    }

    if height == 0 {
        h := m.MapIndex(reflect.ValueOf("height"))
        height = uint16(h.Interface().(amf0.NumberType))
    }
}

然而,您在第一个示例中所做的事情并不少见。有些时候,反射不能解决这个问题。在这种情况下,我对你的类型转换有一些建议。用switch ea := md.(type)代替switch md.(type)。这将允许您删除像ea := md.(*amf0.EcmaArrayType)这样的行。

DRY代码更易于使用。它使得更改更快,更不容易出现bug。然而,当所有重复的代码都在一个地方(比如类型切换)时,出现bug的机会很小。它仍然需要更长的时间来进行更改,但它并不像整个项目中重复的代码那样糟糕。不要害怕重复的类型开关,就像你害怕其他重复的代码一样。

票数 2
EN

Stack Overflow用户

发布于 2012-11-12 03:14:52

在这个特定的例子中,我可能只是向将来的维护者添加注释,指出重复的代码,或者我可能会删除它,如下所示。(游乐场:http://play.golang.org/p/Vc9pOZSNoW)

代码语言:javascript
运行
复制
package main

import "log"

// copied from package amf0
type NumberType float64
type StringType string
type _Object map[StringType]interface{}
type ObjectType _Object
type EcmaArrayType _Object

// test parameter.  comment out one or the other
// var md interface{} = &ObjectType{"height": NumberType(3), "width": NumberType(5)}
var md interface{} = &EcmaArrayType{"height": NumberType(5), "width": NumberType(7)}

func main() {
    var width, height uint16
    ea, ok := md.(*ObjectType)
    if !ok {
        if et, ok := md.(*EcmaArrayType); ok {
            ea = (*ObjectType)(et)
        }
    }
    if ea != nil {
        for k, v := range *ea {
            log.Printf("%v = %v\n", k, v)
        }
        if width == 0 {
            width = uint16((*ea)["width"].(NumberType))
        }
        if height == 0 {
            height = uint16((*ea)["height"].(NumberType))
        }
    }
}

原始文件中的重复代码只是重复的源代码;因为它处理的类型不同,所以编译后的代码也不同。幸运的是,ObjectType案例的编译代码可以通过ea = (*ObjectType)(et)的简单类型转换轻松地处理EcmaArrayType案例。

票数 1
EN

Stack Overflow用户

发布于 2012-11-11 23:57:13

在调用range之前使用类型转换,例如

代码语言:javascript
运行
复制
     range ((* your_desired_type)(*ea))

your_desired_type替换为用于类型转换的实际类型。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13332746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档