2013-03-14 14 views
9

Mam wiersz zawierający 3 numery, które chcę czytać z stdin z fmt.Scanln(), ale ten kod nie zadziała:Jak fmt.Scanln() czytaj na plasterek całkowitymi

X := make([]int, 3) 
fmt.Scanln(X...) 
fmt.Printf("%v\n", X) 

otrzymuję komunikat o błędzie:

cannot use X (type []int) as type []interface {} in function argument 

ja nie rozumiem.

Odpowiedz

4

Na przykład

package main 

import "fmt" 

func intScanln(n int) ([]int, error) { 
    x := make([]int, n) 
    y := make([]interface{}, len(x)) 
    for i := range x { 
     y[i] = &x[i] 
    } 
    n, err := fmt.Scanln(y...) 
    x = x[:n] 
    return x, err 
} 

func main() { 
    x, err := intScanln(3) 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    fmt.Printf("%v\n", x) 
} 

Wejście:

1 2 3 

wyjściowa:

[1 2 3] 
+0

dlaczego nie powoduje to wyniku wyjściowego '[3, 3, 3]'? 'x' będzie intializowane z' 0', które wszystkie wskazują na ten sam adres, gdy testowałem w 'main' func. – dskinner

+0

Widzę, adres '& x [i]' jest unikalny, ale jeśli iteracja z 'dla i, v: = zakres x {...}', adres 'v' nie jest unikalny. – dskinner

+0

co, jeśli zamiast długości 3 moje dane wejściowe nie są statyczne ?. tzn. czasami '' '[1]' '' a czasami '' '[1,2,3,4,5]' '' – javidazac

0

myślę, że prawidłowa wersja powinna być

X := make([]int, 3) 
fmt.Scanln(&X[0], &X[1], &X[2]) 
fmt.Printf("%v\n", X) 
+3

Właściwie mam kilka linii do przetworzenia i nie są one tej samej długości, niektóre mają setki liczb. – Frolik

1

Ten komunikat o błędzie pojawia się b/c nie ma rozsądny sposób przekonwertować []int do []interface{}. Uwaga, dotyczy to plasterka. Tak więc składnia, której używasz, jest poprawna, ale fmt.Scanln oczekuje []interface{}. Ma to wpływ poza pkg fmt.

Powodem, dla którego widziałem, jest to, że Go zapewnia kontrolę nad układem pamięci, więc obecnie nie ma rozsądnego sposobu na konwersję plastra. Oznacza to, że musisz ręcznie wykonać konwersję, zanim przekażesz ją do funkcji oczekującej plastra danego typu. Na przykład:

package main 

import (
    "fmt" 
) 

func main() { 
    x := make([]int, 3) 
    y := make([]interface{}, 3) 
    y[0] = x[0] 
    y[1] = x[1] 
    y[2] = x[2] 

    fmt.Println(y...) 
} 

lub coś trochę bardziej ogólnie:

x := make([]int, 3) 
    y := make([]interface{}, len(x)) 
    for i, v := range x { 
     y[i] = v 
    } 

    fmt.Println(y...) 

Odnośnie konkretnego problemu, zobacz:

x := make([]*int, 3) 
    for i := range x { 
     x[i] = new(int) 
    } 

    y := make([]interface{}, 3) 

    for i, v := range x { 
     y[i] = v 
    } 

    if _, err := fmt.Scanln(y...); err != nil { 
     fmt.Println("Scanln err: ", err) 
    } 

    for _, v := range y { 
     val := v.(*int) 
     fmt.Println(*val) 
    } 
+0

Dzięki, nie dostaję już błędu, ale kiedy drukuję, otrzymuję zera, tak myślę, ponieważ fmt.Scanln() oczekuje referencji. Próbowałem fmt.Scanln (& y ...), bezskutecznie. Dowolny pomysł? – Frolik

+0

Zaktualizowałem z przykładem – dskinner

10

Idiomatic Go byłoby:

func read(n int) ([]int, error) { 
    in := make([]int, n) 
    for i := range in { 
    _, err := fmt.Scan(&in[i]) 
    if err != nil { 
     return in[:i], err 
    } 
    } 
    return in, nil 
} 

interface{} nic nie znaczy. Nie używaj go, jeśli nie musisz.