这个东西可以简化吗

发布于 2022-09-12 22:29:44 字数 550 浏览 21 评论 0

type User struct {
    B0          float64
    B1          float64
    B2          float64
    B3          float64
    B4          float64
    B5          float64
}

switch {
    case money_type == 0:
        User.B0 += money
    case money_type == 1:
        User.B1 += money
    case money_type == 2:
        User.B2 += money
    case money_type == 3:
        User.B3 += money
    case money_type == 4:
        User.B4 += money
    case money_type == 5:
        User.B5 += money
    default:
        return "非法账户", err
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

难理解 2022-09-19 22:29:44

用map 需要改变结构体定义


type User struct {
   B map[float64]floa64
}

if _, ok := User.B[money_type]; ok{
    User.B[money_type] +=  money
}

还可以用反射,不过不推荐,反射会影响性能

type User struct {
   B0          float64
   B1          float64
   B2          float64
   B3          float64
   B4          float64
   B5          float64
}
func (u *User) AddMoney(money float64)  {
   uref := reflect.ValueOf(u).Elem()
   val := uref.FieldByName("B" + fmt.Sprint(money))
   if !val.IsValid(){
      return
 }
   val.Set(reflect.ValueOf(val.Interface().(float64) + money))
}
浅浅淡淡 2022-09-19 22:29:44

想了一个骚操作如下

func addMoney(u *User, moneyType uint, money float64) {
    p := unsafe.Pointer(uintptr(unsafe.Pointer(&u.B0)) + uintptr(moneyType)*unsafe.Sizeof(money))
    *(*float64)(p) += money
}

func Test_unsafe(t *testing.T) {
   u := new(User)
   addMoney(u, 0, 0.01)
   t.Logf("%+v", u)
   addMoney(u, 1, 1.00)
   t.Logf("%+v", u)
   addMoney(u, 2, 2.00)
   t.Logf("%+v", u)
   addMoney(u, 3, 3.00)
   t.Logf("%+v", u)
   addMoney(u, 4, 4.00)
   t.Logf("%+v", u)
   addMoney(u, 5, 5.00)
   t.Logf("%+v", u)
}

    // stdpkg_unsafe_test.go:41: &{B0:0.01 B1:0 B2:0 B3:0 B4:0 B5:0}
    // stdpkg_unsafe_test.go:43: &{B0:0.01 B1:1 B2:0 B3:0 B4:0 B5:0}
    // stdpkg_unsafe_test.go:45: &{B0:0.01 B1:1 B2:2 B3:0 B4:0 B5:0}
    // stdpkg_unsafe_test.go:47: &{B0:0.01 B1:1 B2:2 B3:3 B4:0 B5:0}
    // stdpkg_unsafe_test.go:49: &{B0:0.01 B1:1 B2:2 B3:3 B4:4 B5:0}
    // stdpkg_unsafe_test.go:51: &{B0:0.01 B1:1 B2:2 B3:3 B4:4 B5:5}
骄兵必败 2022-09-19 22:29:44

用映射或iota模拟枚举更合适

山人契 2022-09-19 22:29:44

最好的方法是Codegen,自己写个PYTHON小脚本处理这个吧

蓬勃野心 2022-09-19 22:29:44

用map映射不比这个结构体好吗。。
如果非要优化结构体,那就只能

switch money_type{
    case 0:
        User.B0 += money
    case 1:
        User.B1 += money
    }
撩发小公举 2022-09-19 22:29:44

抛砖引玉一把

package user

import (
    "errors"
    "reflect"
    "testing"
    "unsafe"
)

type User struct {
    B0 int
    B1 int
    B2 int
    B3 int
    B4 int
    B5 int
}

func (u *User) AddMoney(tipe, money int) error {
    switch tipe {
    case 0:
        u.B0 += money
    case 1:
        u.B1 += money
    case 2:
        u.B2 += money
    case 3:
        u.B3 += money
    case 4:
        u.B4 += money
    case 5:
        u.B5 += money
    default:
        return errors.New("failed")
    }
    return nil
}

func (u *User) AddMoney2(tipe, money int) error {
    if tipe >= reflect.TypeOf(*u).NumField() {
        return errors.New("failed")
    }

    ptr := unsafe.Pointer(uintptr(unsafe.Pointer(&u.B0)) + unsafe.Sizeof(money)*uintptr(tipe))

    p := (*int)(ptr)
    *p += money
    return nil
}

func (u User) Equal(dst User) bool {
    if u.B0 != dst.B0 {
        return false
    }
    if u.B1 != dst.B1 {
        return false
    }
    if u.B2 != dst.B2 {
        return false
    }
    if u.B3 != dst.B3 {
        return false
    }
    if u.B4 != dst.B4 {
        return false
    }
    if u.B5 != dst.B5 {
        return false
    }
    return true
}

func (u User) Equal2(dst User) bool {
    tipeSrc := reflect.TypeOf(u)
    valueSrc := reflect.ValueOf(u)
    valueDst := reflect.ValueOf(dst)
    for i := 0; i < tipeSrc.NumField(); i++ {
        if valueSrc.Field(i).Interface() != valueDst.Field(i).Interface() {
            return false
        }
    }
    return true
}

func TestEqual(t *testing.T) {
    cases := []struct {
        src    User
        dst    User
        expect bool
    }{
        {User{B0: 1}, User{B0: 1}, true},
        {User{B0: 1}, User{B0: 0}, false},
        {User{B0: 1}, User{B0: 1, B1: 1}, false},
        {User{B0: 1, B1: 10}, User{B0: 1, B1: 10}, true},
        {User{B0: 1, B1: 10}, User{B0: 1, B1: 11}, false},
    }

    for _, c := range cases {
        if c.src.Equal2(c.dst) != c.expect {
            t.Error("failed")
        }
    }
}

func TestAddMoney(t *testing.T) {
    cases := []struct {
        tipe   int
        money  int
        expect User
    }{
        {0, 999, User{B0: 999}},
        {1, 1, User{B1: 1}},
        {2, 2, User{B2: 2}},
        {3, 3, User{B3: 3}},
        {4, 4, User{B4: 4}},
        {5, 5, User{B5: 5}},
        {6, 6, User{}},
    }

    for _, c := range cases {
        u := User{}
        err := u.AddMoney(c.tipe, c.money)
        if c.tipe < 6 && err != nil {
            t.Error(err.Error())
        }
        if c.tipe > 5 && err == nil {
            t.Errorf("tipe %v should has error", c.tipe)
        }
        if !u.Equal(c.expect) {
            t.Errorf("test failed at tipe %v", c.tipe)
        }
    }
}

// 70~73 ns/op
func BenchmarkEqual(b *testing.B) {
    cases := []struct {
        src    User
        dst    User
        expect bool
    }{
        {User{B0: 1}, User{B0: 1}, true},
        {User{B0: 1}, User{B0: 0}, false},
        {User{B0: 1}, User{B0: 1, B1: 1}, false},
        {User{B0: 1, B1: 10}, User{B0: 1, B1: 10}, true},
        {User{B0: 1, B1: 10}, User{B0: 1, B1: 11}, false},
    }

    for i := 0; i < b.N; i++ {
        for _, c := range cases {
            if c.src.Equal(c.dst) != c.expect {
                b.Error("failed")
            }
        }
    }
}

// 1300~1500 ns/op
func BenchmarkEqual2(b *testing.B) {
    cases := []struct {
        src    User
        dst    User
        expect bool
    }{
        {User{B0: 1}, User{B0: 1}, true},
        {User{B0: 1}, User{B0: 0}, false},
        {User{B0: 1}, User{B0: 1, B1: 1}, false},
        {User{B0: 1, B1: 10}, User{B0: 1, B1: 10}, true},
        {User{B0: 1, B1: 10}, User{B0: 1, B1: 11}, false},
    }

    for i := 0; i < b.N; i++ {
        for _, c := range cases {
            if c.src.Equal2(c.dst) != c.expect {
                b.Error("failed")
            }
        }
    }
}

// 110~120 ns/op
func BenchmarkAddMoney(b *testing.B) {
    cases := []struct {
        tipe   int
        money  int
        expect User
    }{
        {0, 999, User{B0: 999}},
        {1, 1, User{B1: 1}},
        {2, 2, User{B2: 2}},
        {3, 3, User{B3: 3}},
        {4, 4, User{B4: 4}},
        {5, 5, User{B5: 5}},
        {6, 6, User{}},
    }

    for i := 0; i < b.N; i++ {
        for _, c := range cases {
            u := User{}
            err := u.AddMoney(c.tipe, c.money)
            if c.tipe < 6 && err != nil {
                b.Error(err.Error())
            }
            if c.tipe > 5 && err == nil {
                b.Errorf("tipe %v should has error", c.tipe)
            }
            if !u.Equal(c.expect) {
                b.Errorf("test failed at tipe %v", c.tipe)
            }
        }
    }
}

// 400~420 ns/op
func BenchmarkAddMoney2(b *testing.B) {
    cases := []struct {
        tipe   int
        money  int
        expect User
    }{
        {0, 999, User{B0: 999}},
        {1, 1, User{B1: 1}},
        {2, 2, User{B2: 2}},
        {3, 3, User{B3: 3}},
        {4, 4, User{B4: 4}},
        {5, 5, User{B5: 5}},
        {6, 6, User{}},
    }

    for i := 0; i < b.N; i++ {
        for _, c := range cases {
            u := User{}
            err := u.AddMoney2(c.tipe, c.money)
            if c.tipe < 6 && err != nil {
                b.Error(err.Error())
            }
            if c.tipe > 5 && err == nil {
                b.Errorf("tipe %v should has error", c.tipe)
            }
            if !u.Equal(c.expect) {
                b.Errorf("test failed at tipe %v", c.tipe)
            }
        }
    }
}
巴黎盛开的樱花 2022-09-19 22:29:44
  const computeUser = (index, len) => {
    if (index > len) return ('非法账户', err)

    const numberList = Array.from({length: len}).map((_, index) => String(index))
    if (numberList.includes(String(index))) {
      User[`B${index}`] += index
    }

    return computeUser(index, len)
  }

  computeUser(0, 5)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文