2016-04-24 5 views
2

Ich möchte die Kommunikation zwischen zwei Funktionen über Kanäle organisieren. Der Angerufene kann nur Daten an den Kanal senden, während der Anrufer im select darauf wartet. Und ich möchte diese Einschränkung in der callee Signatur zeigen. Eine andere Sache, die ich will, arbeitet mit Typ-Aliasen für Kanäle. Zum Beispiel, anstatt chan string zu haben, möchte ich mit MsgChan definiert als type MsgChan chan string arbeiten. Und ich mit dem Problem konfrontiert - der folgende Code wird nicht kompiliert, wenn uncomment Linie test1(make(Ch)):Typ Alias ​​für Kanal in Go funktioniert seltsam

package main 

import "fmt" 

type Ch chan int 
type ChIn chan<- int 

func test1(in ChIn) { 
    fmt.Println(in) 
} 

func test2(in chan<- int) { 
    fmt.Println(in) 
} 

func main() { 
    //test1(make(Ch)) 
    test1(make(chan int)) 
    test2(make(Ch)) 
    test2(make(ChIn)) 
} 

Ich verstehe nicht, warum ich nicht ein solcher Ansatz nicht verwenden kann?

Antwort

3

test1() hat einen Parameter vom Typ ChIn. Dies ist ein benannter Typ. Sie möchten einen Wert vom Typ Ch übergeben, der ein bidirektionaler Kanaltyp ist und ebenfalls ein benannter Typ ist.

Um dies zu kompilieren, sollte daher der Wert Ch dem Typ ChIn zugewiesen werden können. Dies ist in der Sprachspezifikation nicht erlaubt.

Zitiert Assignability (hervorgehoben die, die hier gilt):

Ein Wert x ist zuordenbar einem variable vom Typ T ("x ist zuordenbar T") in jedem dieser Fälle:

  • x Der Typ ist identisch mit T.
  • x ‚s Typ V und T identische underlying types und mindestens einer von V oder T ist kein genannten Art.
  • T ist ein Schnittstellentyp und ximplementsT.
  • x ist ein bidirektionaler Kanal Wert, T ist ein Kanaltyp, x ‚s Typ V und T identische Elementtypen aufweisen, und mindestens einer der V oder T ist kein genannten Art.
  • x ist der vordeklarierte Bezeichner nil und T ist ein Zeiger, Funktion, Slice, Karte, Kanal oder Schnittstellentyp.
  • x ist ein untypisierter constant darstellbar durch einen Wert vom Typ T.

Sie können es funktioniert, wenn Sie versuchen, einen Wert von unbenannte Art passieren, aber den gleichen zugrunde liegenden Typen, die unter Verwendung einer Typumwandlung erreicht werden kann, zB:

test1((chan int)(make(Ch))) 

Aber Die obige Umwandlung würde den Zweck des Namens Ch besiegen (da Sie das Typliteral wiederholen müssen, um es in einen unbenannten Typ umzuwandeln, so dass Sie es an test1() übergeben können).

Was Sie tun sollten, ist nicht zu verstecken, dass der Typ ein Kanal ist (chan im Typliteral der Typdeklaration nicht enthalten), nur einen neuen Typ für den Elementtyp des Kanals erstellen, zB:

type Msg int 

func test(in chan<- Msg) { 
    fmt.Println(in) 
} 

func main() { 
    test(make(chan Msg)) 
    test(make(chan<- Msg)) 

    ch := make(chan Msg) 
    chIn := (chan<- Msg)(ch) 
    test(chIn) 
} 

es auf dem Go Playground Versuchen.

+0

Großartig! Die Spezifikation sieht so aus, als wäre es genau mein Fall! Ich habe jedoch benannte Typen für den Val-Typ des Kanals verwendet, aber nicht den gesamten Kanal. –

+1

@IvanVelichko Genau was Sie tun sollten, wie in der bearbeiteten Antwort beschrieben. – icza