douxi4114 2016-02-13 22:34 采纳率: 100%
浏览 25
已采纳

更改结构属性值

http://openmymind.net/Things-I-Wish-Someone-Had-Told-Me-About-Go/

Trying to get my head around Go, still pretty new. I know refs and pointers in C and I can't seem to get it working in Go. I've read a number of articles on the issue, and still not really managing to understand and implement a solution.

Characters have health and atk points.

Chars can Attack().

Combat round calls Attack() on which Character can attack this round.

Intent, when Attack() is called on Character, health is changed on another Character.

Currently Health never changes on Characters.

Can someone give me a concise example of how to change the values on objects around the RIGHT way?

package main

import (
    "fmt"
    "math/rand"
    "time"
)

//Character health + atk of
type Character struct {
    Health, Atk int
}

//Attack ... Character can Attack
func (c *Character) Attack(health, atk int) {
    health -= atk
}

//CharacterInterface ... methods for characters
type CharacterInterface interface {
    Attack(health, atk int)
}

func combatRound(p, e Character) {
    whoAtks := rand.Intn(100)
    if whoAtks > 30 {
        p.Attack(e.Health, p.Atk)
        fmt.Println(p.Health)
    } else {
        e.Attack(p.Health, e.Atk)

        fmt.Println(p.Health)
    }
}

func main() {
    //seed rand generator for the current run
    rand.Seed(time.Now().UTC().UnixNano())
    p := Character{20, 5}
    e := Character{20, 5}
    combatRound(p, e)
    fmt.Println("Player Health: %d 
 Enemy Health: %d", p.Health, e.Health)

}
  • 写回答

1条回答 默认 最新

  • dongpigui8898 2016-02-13 23:54
    关注

    In Go, the parameters and receivers of a call to a function or method are always passed by value (by assignment).

    For example,

    package main
    
    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    type Attacker interface {
        Attacks(a *Character)
    }
    
    type Character struct {
        Health, Attack int
    }
    
    func (c *Character) Attacks(a *Character) {
        a.Health -= c.Attack
    }
    
    func combatRound(player, enemy *Character) {
        if rand.Intn(100) <= 30 {
            player, enemy = enemy, player
        }
        player.Attacks(enemy)
    }
    
    func main() {
        rand.Seed(time.Now().UnixNano())
        p := &Character{20, 5}
        e := &Character{20, 5}
        combatRound(p, e)
        fmt.Printf("Player Health: %d
    Enemy Health: %d
    ", p.Health, e.Health)
    }
    

    Output:

    $ go run attack.go
    Player Health: 20 
    Enemy Health: 15
    $ go run attack.go
    Player Health: 20 
    Enemy Health: 15
    $ go run attack.go
    Player Health: 15 
    Enemy Health: 20
    

    The Go Programming Language Specification

    Assignments

    Assignment = ExpressionList assign_op ExpressionList .
    
    assign_op = [ add_op | mul_op ] "=" .
    

    Each left-hand side operand must be addressable, a map index expression, or (for = assignments only) the blank identifier. Operands may be parenthesized.

    A tuple assignment assigns the individual elements of a multi-valued operation to a list of variables. There are two forms. In the first, the right hand operand is a single multi-valued expression such as a function call, a channel or map operation, or a type assertion. The number of operands on the left hand side must match the number of values. For instance, if f is a function returning two values,

    x, y = f()
    

    assigns the first value to x and the second to y. In the second form, the number of operands on the left must equal the number of expressions on the right, each of which must be single-valued, and the nth expression on the right is assigned to the nth operand on the left:

    one, two, three = '一', '二', '三'
    

    The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.

    a, b = b, a  // exchange a and b
    

    The Go statement

    player, enemy = enemy, player
    

    is the second form of a tuple assignment. It's the idiomatic way to swap or exchange two values. The operands on the left and the expressions on the right are evaluated before the assignments take place. The compiler takes care of any temporary variables for you.

    In the combatRound function, for 31 out ot 100 (interval [0, 30] of [0, 100)) calls, on average, roles are reversed or swapped, the enemy (defender) repulses the player (attacker). Swapping the pointers to the Characters reflects the role reversal. and the player's health declines, not the enemy's.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开
  • ¥50 pointpillars等目标检测算法怎么融合注意力机制
  • ¥20 Vs code Mac系统 PHP Debug调试环境配置
  • ¥60 大一项目课,微信小程序
  • ¥15 求视频摘要youtube和ovp数据集
  • ¥15 在启动roslaunch时出现如下问题