2014-05-03 13 views
9

Làm cách nào để chuyển từ điển dưới dạng danh sách các đối số cho hàm như trong Python 3 trong Go?Đến đối số được đặt tên

Python 3:

def bar(a,b,c): 
    print(a,b,c) 

args={c: 1, b: 2, a: 3} 
bar(**args) 

Tới trống:

func bar(a, b, c int) { 
    fmt.Printf("%d, %d, %d", a, b, c) 
} 

func main(){ 
    args := make(map[string]int) 
    args["a"] = 3 
    args["b"] = 2 
    args["c"] = 1 
    // what next ? 
} 
+0

Nó có thể được thực hiện bởi sự phản ánh của Golang không? –

Trả lời

14

Tôi không tin rằng điều này là có thể. Bạn sẽ cần phải sử dụng một cấu trúc để làm bất cứ điều gì, ngay cả từ xa gần này (và nó là một chân dung từ xa)

type Args struct { 
    A, B, C int 
} 

func bar(args *Args) { 
    fmt.Printf("%d, %d, %d", args.A, args.B, args.C) 
} 

func main() { 
    args := new(Args) 
    args.A = 3 
    args.B = 2 
    args.C = 1 
    bar(args) 
} 
+2

Bạn không cần phải gọi nó theo cách đó, sử dụng 'bar (& Args {B: 2})' hoạt động. – OneOfOne

+1

Vâng, tất nhiên, tôi gọi nó theo cách đó để duy trì sự giống nhau về hình ảnh với ví dụ được đưa ra, cho bất cứ điều gì đáng giá. – dskinner

+0

Tôi đã bình chọn cho bạn. – OneOfOne

2

Đối với đầy đủ vì bạn có thể sử dụng những gì dskinner nói, hoặc nếu bạn muốn có một "từ điển" (gọi là bản đồ tại Gò), bạn có thể sử dụng một cách dễ dàng, cho example:

package main 

import "log" 

type ArgsMap map[string]interface{} 

func bar(am ArgsMap) { 
    if v, ok := am["foo"].(string); ok { 
     log.Println("bar", v) 
    } else { 
     log.Println("bar no foo") 
    } 
} 

// Or 

type Args struct { 
    foo  string 
    boo  int 
    a, b, c float32 
} 

func bar2(a Args) { 
    if a.foo != "" { 
     log.Println("bar2", a.foo) 
    } else { 
     log.Println("bar2 no foo") 
    } 
} 

func main() { 
    bar(ArgsMap{"foo": "map", "blah": 10}) 
    bar(ArgsMap{}) 

    bar2(Args{foo: "struct"}) 
    bar2(Args{}) 
} 
1

không có tương đương trực tiếp cú pháp *args/**kwargs của Python. Bạn cần sử dụng một trong các giải pháp được nêu trong các câu trả lời khác.

Trong trường hợp bạn chỉ cần chuyển số lượng đối số không xác định, bạn có thể thực hiện chức năng của mình variadic.

package main 

import (
    "fmt" 
) 

func bar(numbers ...int) { 
    fmt.Printf("%d\n", numbers) 
} 

func main() { 
    bar(3, 2, 1)  // prints [3 2 1] 
    bar(5, 4, 3, 2, 1) // prints [5 4 3 2 1] 
} 

Play

9

Bên cạnh những câu trả lời khác, mà tôi thấy không cần phải lặp lại, lưu ý rằng Go chức năng tự động giải nén sẽ gọi với nhiều lý lẽ trở lại cung cấp:

  1. Mỗi giá trị trả lại là thông số của hàm
  2. Mọi thông số là giá trị trả lại của hàm

(Tức là, các loại danh sách đối số của hàm giống hệt với danh sách trả về của hàm khác).

func Args() (a int, b int, c int) { 
    return 1,2,3 
} 

func Bar(a,b,c int) { 
    fmt.Println(a,b,c) 
} 

func main() { 
    Bar(Args()) 
} 

Sẽ in 1,2,3. Rõ ràng ví dụ này là một chút ngớ ngẩn, nhưng tôi thấy điều này bao gồm hầu hết các trường hợp tuple và dict giải nén như các đối số trong Python, có xu hướng là một cách nhanh chóng và dơ bẩn để truyền các giá trị trả về của một hàm như các đối số của hàm khác.

+2

tuyệt vời, đây là một trong những trường hợp tôi đã nghĩ rằng tôi chỉ không nhận thức được, tôi đã không nhận ra bạn có thể vượt qua những giá trị giải nén trực tiếp đến func khác. – dskinner

1

Điều này không được kiểm tra kỹ lưỡng đối với một loạt các giá trị, nhưng nó hoạt động trong một vài trường hợp đơn giản. Cảm thấy tự do để mở rộng hơn nữa cho nhu cầu của riêng bạn. Nó cũng không đảm bảo được bất cứ điều gì giống như cách tốt nhất để làm điều này, và kiểm tra lỗi còn lại là một bài tập cho người đọc.

func parseArguments(args ...interface{}) map[string]interface{} { 
    if args == nil { 
     return nil 
    } 
    if x,ok := args[0].(map[string]interface{}); ok { 
     return x 
    } 
    x := map[string]interface{}{} 
    for i := 0; i < len(args); i += 2 { 
     x[ args[i].(string) ] = args[i+1] 
    } 
    return x 
} 

func DoSomethingCool(x ...interface{}) { 
    args := parseArguments(x); 
    // args is now a map of type map[string]interface{} 
} 

Bây giờ bạn có thể gọi DoSomethingCool() trong bất kỳ trong các cách sau:

// No arguments 
DoSomethingCool() 

// These two are equivalent, and result in 
// args = map[string]interface{}{ 
//  "foo": "bar", 
//  "baz": "qux", 
// } 
DoSomethingCool(map[string]string{"foo": "bar", "baz": "qux"}) 
DoSomethingCool("foo","bar","baz","qux") 

// Or you can even mix types for the keys, thanks to interface{} 
// These two are also equivalents and result in 
// args = map[string]interface{}{ 
//  "foo": 20, 
//  "bar": false, 
// } 

DoSomethingCool(map[string]interface{}{"foo": 20, "bar": false}) 
DoSomethingCool("foo",20,"bar",false) 

Nếu bạn không có nhu cầu để trộn các loại giá trị, bạn có thể chỉ cần cũng sử dụng map[string]string tôi tưởng tượng.

+0

Bạn không có nghĩa là các loại giá trị kết hợp trên loại cuối cùng? – Aicos

+0

@ Aicos: Có, cảm ơn bạn đã thông báo lỗi. Tôi đã sửa câu trả lời. – Flimzy

Các vấn đề liên quan