简体   繁体   中英

Go change struct property values

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 \n Enemy Health: %d", p.Health, e.Health)

}

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\nEnemy Health: %d\n", 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM