2013-05-30 30 views
9

tôi có thể chuyển đổi một int để một float64 như thế này:Go loại khẳng định chuyển đổi

var a int = 10 
var b float64 = float64(a) 

Liên quan đến gõ khẳng định, hiệu quả Go: 'Nguồn gốc loại hoặc phải được loại bê tông tổ chức bởi giao diện, hoặc loại giao diện thứ hai mà giá trị có thể được chuyển đổi thành '.

Với ý nghĩ đó, tại sao sau thất bại:

func foo(a interface{}) { 
    fmt.Println(a.(float64)) 
} 

func main() { 
    var a int = 10 
    foo(a) 
} 

Điều này gây ra một panic: interface conversion: interface is int, not float64.

Lưu ý rằng Go Spec nói:

'Đối với một biểu thức x kiểu giao diện và một loại T, khái niệm chính

x.(T) 

khẳng định rằng x là không bằng không và rằng giá trị được lưu trữ trong x thuộc loại T. '

Điều gì mâu thuẫn với tuyên bố Hiệu quả Go nhưng dường như phù hợp hơn với những gì tôi thấy.

Trả lời

9

This sentence trong Bắt đầu hiệu quả có vẻ thực sự gây nhầm lẫn. Có vẻ như tác giả đã suy nghĩ về cấu trúc tại thời điểm đó.

The chapter on assertions in the specification là rõ ràng hơn nhiều.

Đối với một biểu thức x kiểu giao diện và một loại T, biểu chính

x (T) khẳng định rằng x là không bằng không và rằng giá trị được lưu trữ trong x là loại T. Ký hiệu x. (T) được gọi là xác nhận kiểu.

Chính xác hơn, nếu T không phải là loại giao diện, x. (T) xác nhận rằng loại động x là giống với loại T. Trong trường hợp này, T phải triển khai loại (giao diện) của x ; nếu không xác nhận kiểu là không hợp lệ do không thể lưu trữ giá trị loại T. Nếu T là loại giao diện, x. (T) xác nhận rằng kiểu động của x triển khai giao diện T.

Thực tế you can convert your int to a float (và ngược lại) không có nghĩa là bạn có thể khẳng định chúng cùng loại.

+0

đồng ý, tuy nhiên theo đề xuất của thông điệp hoảng loạn thời gian chạy, thao tác thực sự là 'chuyển đổi giao diện', chứ không phải xác nhận. Sẽ tốt hơn nếu kiểu chuyển đổi này có thể xảy ra một cách tự nhiên. – Ferguzz

+0

Bạn có thể thực hiện chuyển đổi loại. Bạn nghĩ gì về tự nhiên hơn? –

+0

@Ferguzz: Chuyển khá rõ ràng trong tất cả các chuyển đổi của nó, có _no_ chuyển đổi ngầm hoặc tự động. Đây là một điều rất tốt. Các loại "chuyển đổi tự nhiên" hoàn toàn trái ngược với rõ ràng. – Volker

8

Loại phải hoặc là kiểu dữ liệu cụ tổ chức bởi giao diện, hoặc một giây giao diện loại mà giá trị có thể được chuyển đổi sang

này về cơ bản giải thích following:

package main 

import "fmt" 

type Stringer interface { 
    String() 
} 

type Byter interface { 
    Bytes() 
} 

type Stringbyter interface { 
    Stringer 
    Byter 
} 

type Polymorphic float64 

func (p *Polymorphic) String() {} 

func (p *Polymorphic) Bytes() {} 

func main() { 
    i := interface{}(new(Polymorphic)) 
    if _, ok := i.(Stringer); ok { 
     fmt.Println("i can be asserted to Stringer") 
    } 
    if _, ok := i.(Byter); ok { 
     fmt.Println("i can be asserted to Byter") 
    } 
    if _, ok := i.(Stringbyter); ok { 
     fmt.Println("i can be asserted to Stringbyter") 
    } 
    if _, ok := i.(*Polymorphic); ok { 
     fmt.Println("i can be asserted to *Polymorphic") 
    } 
    if _, ok := i.(int); ok { 
     fmt.Println("i can be asserted to int") // Never runs 
    } 
} 

Xác nhận với int không thành công vì đó là loại bê tông (ngược với loại giao diện) ich không phải là số *Polymorphic.

0

Bạn chỉ có thể nhập khẳng định từ loại giao diện cho loại cơ bản.Trong trường hợp này là int. Sau đó, bạn sử dụng chuyển đổi loại từ int thành float64

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