valor unica servicio propuesta producto oferta marketing empresas elementos ejemplos cola coca agregado go error-handling return-value multiple-return-values

go - unica - MĂșltiples valores en contexto de un solo valor



propuesta de valor ejemplos pdf (5)

Debido al manejo de errores en Go, a menudo termino con múltiples funciones de valores. Hasta ahora, la forma en que he manejado esto ha sido muy desordenada y estoy buscando las mejores prácticas para escribir código más limpio.

Digamos que tengo la siguiente función:

type Item struct { Value int Name string } func Get(value int) (Item, error) { // some code return item, nil }

¿Cómo puedo asignar una nueva variable al elemento? item.Value elegancia. Antes de introducir el manejo de errores, mi función acaba de devolver un item y simplemente podría hacer esto:

val := Get(1).Value

Ahora hago esto:

item, _ := Get(1) val := item.Value

¿No hay una manera de acceder directamente a la primera variable devuelta?


¿Qué tal este camino?

package main import ( "fmt" "errors" ) type Item struct { Value int Name string } var items []Item = []Item{{Value:0, Name:"zero"}, {Value:1, Name:"one"}, {Value:2, Name:"two"}} func main() { var err error v := Get(3, &err).Value if err != nil { fmt.Println(err) return } fmt.Println(v) } func Get(value int, err *error) Item { if value > (len(items) - 1) { *err = errors.New("error") return Item{} } else { return items[value] } }


En el caso de una función de retorno de varios valores, no puede hacer referencia a campos o métodos de un valor específico del resultado al llamar a la función.

Y si uno de ellos es un error , está allí por una razón (que es la función que puede fallar) y no debe omitirlo porque si lo hace, su código posterior también podría fallar miserablemente (por ejemplo, lo que provocaría un pánico en el tiempo de ejecución).

Sin embargo, puede haber situaciones en las que sepa que el código no fallará en ninguna circunstancia. En estos casos, puede proporcionar una función auxiliar (o método) que descarte el error (o genere un pánico en tiempo de ejecución si aún se produce).
Este puede ser el caso si proporciona los valores de entrada para una función desde el código y sabe que funcionan.
Grandes ejemplos de esto son los paquetes de template y regexp : si proporciona una plantilla válida o expresiones regulares en tiempo de compilación, puede estar seguro de que siempre se pueden analizar sin errores en tiempo de ejecución. Por esta razón, el paquete de template proporciona la función Must(t *Template, err error) *Template y el paquete regexp proporciona la función MustCompile(str string) *Regexp : no devuelven error porque su uso previsto es donde la entrada está garantizado para ser válido.

Ejemplos:

// "text" is a valid template, parsing it will not fail var t = template.Must(template.New("name").Parse("text")) // `^[a-z]+/[[0-9]+/]$` is a valid regexp, always compiles var validID = regexp.MustCompile(`^[a-z]+/[[0-9]+/]$`)

De vuelta a su caso

SI puede estar seguro de que Get() no producirá un error para ciertos valores de entrada, puede crear una función auxiliar Must() que no devolverá el error pero generará un pánico en tiempo de ejecución si aún ocurre:

func Must(i Item, err error) Item { if err != nil { panic(err) } return i }

Pero no debe usar esto en todos los casos, solo cuando esté seguro de que tiene éxito. Uso:

val := Must(Get(1)).Value

Alternativa / Simplificación

Incluso puede simplificarlo aún más si incorpora la llamada Get() en su función auxiliar, llamémosla MustGet :

func MustGet(value int) Item { i, err := Get(value) if err != nil { panic(err) } return i }

Uso:

val := MustGet(1).Value

Vea algunas preguntas interesantes / relacionadas:

cómo analizar múltiples retornos en golang

Regrese el mapa como ''ok'' en Golang en funciones normales


No, no puede acceder directamente al primer valor.

Supongo que un truco para esto sería devolver una matriz de valores en lugar de "item" y "err", y luego simplemente hacer item, _ := Get(1)[0] pero no recomendaría esto.


No, pero eso es bueno, ya que siempre debe manejar sus errores.

Existen técnicas que puede emplear para diferir el manejo de errores, consulte Los errores son valores de Rob Pike.

ew := &errWriter{w: fd} ew.write(p0[a:b]) ew.write(p1[c:d]) ew.write(p2[e:f]) // and so on if ew.err != nil { return ew.err }

En este ejemplo de la publicación del blog, ilustra cómo puede crear un tipo errWriter que errWriter manejo de errores hasta que errWriter llamar a write .


Sí hay.

Sorprendente, ¿eh? Puede obtener un valor específico de un retorno múltiple utilizando una función de mute simple:

package main import "fmt" import "strings" func µ(a ...interface{}) []interface{} { return a } type A struct { B string C func()(string) } func main() { a := A { B:strings.TrimSpace(µ(E())[1].(string)), C:µ(G())[0].(func()(string)), } fmt.Printf ("%s says %s/n", a.B, a.C()) } func E() (bool, string) { return false, "F" } func G() (func()(string), bool) { return func() string { return "Hello" }, true }

https://play.golang.org/p/IwqmoKwVm-

Observe cómo selecciona el número de valor tal como lo haría con un segmento / matriz y luego el tipo para obtener el valor real.

Puedes leer más sobre la ciencia detrás de eso en este artículo . Créditos al autor.