Go、一流功能和最佳实践

Go、一流功能和最佳实践,go,global-variables,first-class-functions,Go,Global Variables,First Class Functions,在过去的几天里,我遇到了一个难题,那就是如何最好地解决一类函数的问题(将一个可调用函数分配给某个变量),以及在效率方面的最佳实践 假设我正在编写一个Yugioh纸牌游戏,我希望每一张纸牌类型至少具有以下属性: type card struct { name string text string } 我一直在苦苦思索在何处(以及如何)对每张卡的各个功能进行编程。我目前确信,第一类函数的最佳位置是键入card struct,并像在Python()中一样创建一个“可调用”的新属性 我

在过去的几天里,我遇到了一个难题,那就是如何最好地解决一类函数的问题(将一个可调用函数分配给某个变量),以及在效率方面的最佳实践

假设我正在编写一个Yugioh纸牌游戏,我希望每一张纸牌类型至少具有以下属性:

type card struct {
    name string
    text string
}
我一直在苦苦思索在何处(以及如何)对每张卡的各个功能进行编程。我目前确信,第一类函数的最佳位置是
键入card struct
,并像在Python()中一样创建一个“可调用”的新属性

我对高效的代码不是很在行,我完全理解我可能会在早期进行优化;然而,我需要编写成百上千张这样的卡片,如果这些可调用的内容存在于全局范围内,并且严重依赖于类型断言,这会使程序运行缓慢,那么重新组织代码时就会遇到麻烦


你能从我的方法中看到什么突出的问题吗?我是否正确地使用了第一类函数,还是存在一些我看不到的突出性能问题?我们将非常感谢您的任何帮助

感谢所有帮助我回答这个问题的人。看来我仍然在使用我的脚本语言思维来尝试用编译语言解决问题。我不再试图创建最终导致代码更难阅读的接口,而是需要在自定义类型定义中更加严格,并为每种类型的卡片效果实现不同的函数类型。如此严格的执行也将允许游戏中存在具有多种效果的牌

package main

type card struct {
    name string
    text string
}

type monsterCard struct {
    card
    attack int
    defense int
}

type buffEffect struct {
    monsterCard
    fn buff
}

type setValueEffect struct {
    monsterCard
    fn swap
}

type buff func(target *monsterCard)

type swap func(target *monsterCard, value int)

var increaseAttack buff = func(target *monsterCard)  {
    target.attack += 100
}

var setAttackValue swap = func(target *monsterCard, value int) {
    target.attack = value
}

func main()  {
    m1 := buffEffect{
        monsterCard: monsterCard{
            card:    card{
                name: "Celtic Guardian",
            },
            attack:  1400,
            defense: 1200,
        },
        fn:          increaseAttack,
    }
    m2 := setValueEffect{
        monsterCard: monsterCard{
            card:    card{
                name: "Dark Magician",
            },
            attack:  2500,
            defense: 2100,
        },
        fn:          setAttackValue,
    }
    m1.fn(&m1.monsterCard)
    m2.fn(&m2.monsterCard, 100)
}

您可以在需要时使用普通函数和闭包:

type card struct {
    name string
    text string
    fn   func(*monsterCard)
}

type monsterCard struct {
    card
    attack  int
    defense int
}

func (mc *monsterCard) call() {
    mc.fn(mc)
}

func increaseAttack(mc *monsterCard) {
    mc.attack += 100
}

func switchStats(mc *monsterCard) {
    mc.attack, mc.defense = mc.defense, mc.attack
}


func updateTextAndAttack(text string, attack int) func(mc *monsterCard) {
    return func(mc *monsterCard) {
        mc.text, mc.attack = text, attack
    }
}
type card struct {
    name string
    text string
}

type monsterCard struct {
    card
    attack  int
    defense int
}

func (mc *monsterCard) increaseAttack() {
    mc.attack += 100
}

func (mc *monsterCard) switchStats() {
    mc.attack, mc.defense = mc.defense, mc.attack
}

func (mc *monsterCard) updateTextAndAttack(text string, attack int) func() {
    return func() {
        mc.text, mc.attack = text, attack
    }
}

您还可以在需要时使用普通方法和闭包:

type card struct {
    name string
    text string
    fn   func(*monsterCard)
}

type monsterCard struct {
    card
    attack  int
    defense int
}

func (mc *monsterCard) call() {
    mc.fn(mc)
}

func increaseAttack(mc *monsterCard) {
    mc.attack += 100
}

func switchStats(mc *monsterCard) {
    mc.attack, mc.defense = mc.defense, mc.attack
}


func updateTextAndAttack(text string, attack int) func(mc *monsterCard) {
    return func(mc *monsterCard) {
        mc.text, mc.attack = text, attack
    }
}
type card struct {
    name string
    text string
}

type monsterCard struct {
    card
    attack  int
    defense int
}

func (mc *monsterCard) increaseAttack() {
    mc.attack += 100
}

func (mc *monsterCard) switchStats() {
    mc.attack, mc.defense = mc.defense, mc.attack
}

func (mc *monsterCard) updateTextAndAttack(text string, attack int) func() {
    return func() {
        mc.text, mc.attack = text, attack
    }
}

您是否考虑过使用普通方法?只有当您打算在结构实例的生命周期内更改函数时,将函数指针作为结构的成员变量才有意义。否则,简单的旧方法就会奏效。在您的例子中,您似乎正在使用类型开关来确定函数是什么,因此简单地将它们定义为对应类型的方法将是最干净的方法。这种方法不考虑多个效果,您也希望在不同的时间应用不同的效果。使每张卡成为自己的类型,并为每张卡可能实现或可能不实现的每个效果定义一个接口。您可以为基本统计数据嵌入一个公共类型。
接口{}
从来都不是最佳实践。看起来您需要一种叫做“多重分派”或“多重方法”的东西。Go不支持ootb。@mkopriva使用常规函数是我的第一个想法,但我不知道如何使每张卡的结构指向特定的函数。在Python中似乎是可能的,但在Go中却不可能。