go - 将 int 或 float 分配给接口(interface)是否会在内部导致 block 分配?

标签 go

我想知道 Go 接口(interface)是如何实现的,以及当我传递一个 int 或一个 float64 时,它是否意味着在堆上分配一个 block 。
是否有可能知道它何时意味着分配?
我问这个是因为我有多种方法来实现一个程序,而且我更愿意选择一个最有效的方法,因为这种选择很容易先验。
一种设计意味着使用接口(interface)传递值,我传递 int、float 和 nil 值。一种可能的设计是也传递一个包含错误和 int 值的结构值。但如果内存分配“昂贵”,我可以避免这种情况。问题是努力是否值得。
注意:请不要告诉我不要过早优化。我知道这个原理。在某些情况下,您确实想要优化,然后最好知道如何或如何不实现低效的代码。

最佳答案

您的 基准测试,它会告诉你(这里没有内存分配 ):
1.

go test -bench=. -benchmem -benchtime=1000000000x
# BenchmarkMethod1-8 1000000000 6.58  ns/op  0 B/op  0 allocs/op
# BenchmarkMethod2-8 1000000000 0.806 ns/op  0 B/op  0 allocs/op
代码:
package main

import (
    "testing"
)

func BenchmarkMethod1(b *testing.B) {
    for i := 0; i < b.N; i++ {
        method1(42)
        method1(4.2)
    }
}
func BenchmarkMethod2(b *testing.B) {
    for i := 0; i < b.N; i++ {
        method2(intOrFloat{isInt: true, i: 42})
        method2(intOrFloat{f64: 4.2})
    }
}

func method1(object interface{}) {
    switch v := object.(type) {
    case int:
        i = v
    case float64:
        f64 = v
    }
}

func method2(object intOrFloat) {
    if object.isInt {
        i = object.i
    } else {
        f64 = object.f64
    }
}

type intOrFloat struct {
    isInt bool
    i     int
    f64   float64
}

var i int
var f64 float64
  • go test -bench=. -benchmem -benchtime=100x
    # BenchmarkMethod1-8  100  4202731 ns/op  0 B/op  0 allocs/op
    # BenchmarkMethod2-8  100  3412604 ns/op  0 B/op  0 allocs/op
    
    代码:
    package main
    
    import (
        "testing"
    )
    
    func BenchmarkMethod1(b *testing.B) {
        for i := 0; i < b.N; i++ {
            outputInt = outputInt[:0]
            outputf64 = outputf64[:0]
            for i := 0; i < max; i++ {
                switch v := inputIface[i].(type) {
                case int:
                    outputInt = append(outputInt, v)
                case float64:
                    outputf64 = append(outputf64, v)
                }
            }
        }
    }
    func BenchmarkMethod2(b *testing.B) {
        for i := 0; i < b.N; i++ {
            outputInt = outputInt[:0]
            outputf64 = outputf64[:0]
            for i := 0; i < max; i++ {
                if inputStruct[i].isInt {
                    outputInt = append(outputInt, inputStruct[i].i)
                } else {
                    outputf64 = append(outputf64, inputStruct[i].f64)
                }
            }
        }
    }
    
    type intOrFloat struct {
        isInt bool
        i     int
        f64   float64
    }
    
    func init() {
        for i := 0; i < max; i++ {
            if i%2 == 0 {
                inputIface[i] = float64(i)
                inputStruct[i] = intOrFloat{f64: float64(i)}
            } else {
                inputIface[i] = int(i)
                inputStruct[i] = intOrFloat{isInt: true, i: i}
            }
        }
    }
    
    const max = 1_000_000
    
    var inputIface = make([]interface{}, max)
    var inputStruct = make([]intOrFloat, max)
    
    var outputf64 = make([]float64, 0, max)
    var outputInt = make([]int, 0, max)
    
    

    关于go - 将 int 或 float 分配给接口(interface)是否会在内部导致 block 分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65156124/

    相关文章:

    go - 为什么 GoLang 方法给出编译错误?

    tcp - Google Go EOF 使用 Read() 从连接读取

    json - 使用多层嵌套映射解码 JSON

    json - AWS Cognito 解码 JWKS.json

    regex - 什么是正则表达式来匹配 =,空格分隔后的所有事件?

    go - 缓冲 channel 阻止执行

    go - JSON1 支持 go-sqlite3 使用 gorm

    go - Go 中的映射不是线程安全的意味着什么?

    for-loop - 暂停for循环的执行

    go - 当方法实际上没有丢失时接口(interface)转换 panic