Escribió un paquete en Go. ¿Qué hice mal? ¿Qué hice lo correcto? -- beginner campo con game campo con go camp codereview Relacionados El problema

Wrote a package in Go. What did I do wrong? What did I do right?


5
vote

problema

Español

Escribí un paquete de jugador en Go. Se construye correctamente, pero me encantaría una revisión sobre lo que hice y no hice "el camino". Soy nuevo en la codificación en el idioma, aunque he conseguido a mitad de camino a través de Ivo Balbaert's "El camino a ir".

El código consiste en una estructura y un montón de colegios y consignos para la estructura.

  long7  
Original en ingles

I wrote a Player package in Go. It builds correctly, but I would love a review on what I did and did not do "the Go way". I'm new to coding in the language, although I've gotten about halfway through Ivo Balbaert's "The Way To Go".

The code consists of a struct and a bunch of setters and getters for the struct.

package Player  import (     "math/rand"     "time" )  type Player struct {     name   string     race   string     id     int64     pos    Position     facing int64     health int64     wpn_id int64   // Weapon id     is_buf bool    // Has buff     buf_mt float64 // Buff multiplier }  type Position map[int64]int64  func (P *Player) SetPlayer(name string, race string) *Player {     rand := rand.New(rand.NewSource(time.Now().UnixNano()))      P.name = name     P.race = race     P.id = rand.Int63()     P.pos = Position{0: 0}     P.facing = 0     P.health = 100     P.wpn_id = 0     P.is_buf = false     P.buf_mt = 0.0      return P }  func (P *Player) GetPlayer() *Player {     return P }  func (P *Player) SetPosition(x int64, y int64) {     P.pos = Position{x: y} }  func (P *Player) GetPosition() Position {     return P.pos }  func (P *Player) SetFacing(direction int64) {     P.facing = direction }  func (P *Player) GetFacing() int64 {     return P.facing }  func (P *Player) SetHealth(amount int64, direction string) {     if direction == "down" {         P.health = P.health - amount     } else {         P.health = P.health + amount     } }  func (P *Player) GetHealth() int64 {     return P.health }  func (P *Player) SetWeaponId(weapon_id int64) {     P.wpn_id = weapon_id }  func (P *Player) GetWeaponId() int64 {     return P.wpn_id }  func (P *Player) SetIsBuffed(is_buff bool) {     P.is_buf = is_buff }  func (P *Player) GetIsBuffed() bool {     return P.is_buf }  func (P *Player) SetBuffMultiplier(multiplier float64) {     P.buf_mt = multiplier }  func (P *Player) GetBuffMultiplier() float64 {     return P.buf_mt } 
        

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

Esto es bastante desnudo en cuanto a los paquetes, pero hay cosa que se puede mejorar aquí.

En primer lugar, para crear un objeto de jugador, alguien tendrá que hacer el equivalente a:

  if [ -z "${instance}" ]; then 8  

Esto es un poco molesto. Prefiero crear una función que construye un 99887766555443329 :

  [[ ... ]]0  

También podemos usar un poco de azúcar sintáctica para acortar la inicialización real:

  [[ ... ]]1  

Realmente no entiendo cuál es el punto de la función:

  [[ ... ]]2  

se supone que es. Se necesita un jugador, y devuelve el mismo jugador, un no-op.

No estoy seguro de por qué use un [[ ... ]]3 para la posición, cuando 2 enteros hará:

  [[ ... ]]4  

En la siguiente función:

  [[ ... ]]5  

[[ ... ]]6 podría ser un tipo de enumio:

  [[ ... ]]7  

Aunque esto está exagerado aquí, y yo iría con la sugerencia de @ Winstonewert y simplemente pasaría un número positivo o negativo que se puede usar para modificar la salud del jugador.

Un tipo con muchos conseguidos y colonos no encaja realmente con la IT "Mantra". De hecho, consideraría esto un poco de anti-patrón en la mayoría de los idiomas: si vas a escribir tanto 998877766554433388 y 99887766555443339 funciones, sin verificar realmente los argumentos o hacer cumplir las restricciones, puede simplemente dar acceso directo a la variable subyacente. Sin embargo, esto es discutible y sé que algunas personas estarán en desacuerdo, por lo que no lo haré, no lo haré.

 

This is fairly bare-bones as far as packages go, but there are thing that can be improved here.

Firstly, to create a player object, someone is going to need to do the equivalent of:

player := new(Player) player.SetPlayer(...) 

This is a bit annoying. I'd much rather create a function that constructs a fully initialised Player:

func NewPlayer(name string, race string) *Player {     ... } 

We can also use some syntactic sugar to shorten the actual initialisation:

func NewPlayer(name_ string, race_ string) *Player {     rand := rand.New(rand.NewSource(time.Now().UnixNano()))     return &Player{name: name_, race: race_, id: rand.Int63(), pos: Position{0: 0},                     facing: 0, health: 100, wpn_id: 0, is_buf: false, buf_mt: 0.0} } 

I don't really understand what the point of the function:

func (P *Player) GetPlayer() *Player {     return P } 

is supposed to be. It takes a player, and returns the same player - a no-op.

I'm also not sure why you use a map for position, when 2 integers will do:

type Position struct {     x int64     y int64 } 

In the following function:

func (P *Player) SetHealth(amount int64, direction string) {     if direction == "down" {         P.health = P.health - amount     } else {         P.health = P.health + amount     } } 

direction could be an enum-like type:

type Direction uint8  const (     DOWN Direction = iota,     UP   Direction = iota )  func (P *Player) SetHealth(amount int64, direction Direction) {     switch direction {     case DOWN: P.health -= amount     case UP: P.health += amount     default: panic("Unknown direction type!")     } } 

Although this is overkill here, and I'd go with @WinstonEwert's suggestion and just pass in either a positive or negative number that can be used to modify the player health.

A type with a lot of getters and setters doesn't really fit with the Go "mantra". In fact, I'd consider this a bit of an anti-pattern in most languages - if you're going to write both Get and Set functions, without really checking arguments or enforcing constraints, you may as well just give direct access to the underlying variable. This is debatable, however, and I know some people will disagree, so I'll won't belabour the point.

 
 
     
     
3
 
vote
  if [[ -z $instance ]]; then 0  

Debe hacerlo una vez al principio su programa y pasarlo a donde necesita el generador de números aleatorios. Para casi todas las aplicaciones, solo debe sembrar el generador de números aleatorios una vez, no cada vez que lo use.

 
func (P *Player) SetPlayer(name string, race string) *Player {     rand := rand.New(rand.NewSource(time.Now().UnixNano())) 

You should do this once at the beginning your program, and pass it around to where you need the random number generator. For almost all applications, you should only seed the random number generator once, not each time you use it.

 
 
1
 
vote

interruptor

  package Player   

a

  package player   

Las recomendaciones efectivas de GO son: "Por convención, los paquetes se administran en minúsculas, nombres de una sola palabra; No debe haber necesidad de guiones bajos o cápsulas mibadas". http://golang.org/doc/effective_go.html#package-names

interruptor

  func NewPlayer(name string, race string) *Player    

a

  func New(name string, race string) *Player    

Cualquier código que se hace referencia a su paquete ya estará utilizando el reproductor. En frente, por lo que tiene jugador. Niew (...) es un poco más apretado que el jugador. Nomewplayer (...). Si su paquete tenía varios constructores, tendría sentido mantenerlo NewPlayer, pero para un paquete de un solo propósito, se prefiere cambiar a NEW. http://golang.org/doc/effective_go.html#package-names

 

Switch

package Player 

to

package player 

Effective Go's recommendations are: "By convention, packages are given lower case, single-word names; there should be no need for underscores or mixedCaps". http://golang.org/doc/effective_go.html#package-names

Switch

func NewPlayer(name string, race string) *Player  

to

func New(name string, race string) *Player  

Any code referencing your package already will be using player. in front, so having player.New(...) is a little tighter than player.NewPlayer(...). If your package had several constructors it would make sense to keep it NewPlayer, but for a single purpose package, switching to New is preferred. http://golang.org/doc/effective_go.html#package-names

 
 
 
 

Relacionados problema

5  Herramienta para calcular el tiempo promedio que toma para una solicitud de tracción GitHub para fusionar  ( Tool to calculate the average time that takes for a github pull request to get m ) 
Estoy aprendiendo, y este es mi primer intento de una herramienta de línea de comandos que usa la API de GitHub para calcular el tiempo promedio que toma una ...

7  Árboles binarios equivalentes (un recorrido por go)  ( Equivalent binary trees a tour of go ) 
Cualquier sugerencia sobre cómo mejorar el código que se muestra a continuación para la Ejercicio de go-tour ? < / p> Descripción del ejercicio: Puede ha...

2  Consulta Seleccione e inserte si no existe  ( Query select and insert if not exists ) 
¿Hay alguna buena manera de hacer este método más corto? "var text = document.getElementById('text'); var greeting = ['Hello. I am a console wannabe.', ...

6  Implementando una API de descanso en Ir usando Gorilla / Mux y Gorm  ( Implementing a rest api in go using gorilla mux and gorm ) 
Mientras está aprendiendo, decidí implementar una API de descanso simple para conocer el idioma y, dado que estoy inexperto en el principio, apreciaría cualq...

4  Pasando alrededor del contexto.Context en Golang  ( Passing around context context in golang ) 
Actualmente soy "graciosamente" Manejar el servidor HTTP net/http Apagado que funciona perfectamente bien ( No le estoy pidiendo que revise el cierre del se...

1  Solicitar enrutador escrito en Go  ( Request router written in go ) 
Comencé a aprender Idioma y me imaginé escribir otro enrutador de solicitud, ya que lo necesito para mi próximo proyecto Go. Como es lo que es lo primero que ...

3  Archivo de registro diferido Cerrar  ( Deferred log file close ) 
Mi código funciona en que se compila, y cuando se ejecuta, escribe un archivo de registro utilizando un escritor búfer. pero me pregunto si: Soy correcto...

1  Formateo de un archivo de texto cambia como HTML  ( Formatting a changes text file as html ) 
Tengo una función que se usa para convertir texto (un archivo de cambios) en HTML para leer. La función es esencialmente basada en línea: si la línea es de es...

12  Entrevista de concurrencia  ( Concurrency interview ) 
Un poco de vuelta, tuve una entrevista donde plantearon un problema, en resumen: Mire un determinado directorio, y procese archivos JSON entrantes Estos ...

7  Descarga concurrente en Go  ( Concurrent download in go ) 
Escribí un programa para descargar archivos en manera concurrente / paralelo (gomaxprocs & gt; 1). Este es mi programa 2 nd (no juguete) escrito en Go. Po...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos