英文:
What does asterisk (*struct) notation mean in golang
问题
// NewReaderSize返回一个新的Reader,其缓冲区至少具有指定的大小。如果参数io.Reader已经是具有足够大的大小的Reader,则返回底层Reader。
func NewReaderSize(rd io.Reader, size int) *Reader {
// 它已经是一个Reader了吗?
b, ok := rd.(*Reader)
if ok && len(b.buf) >= size {
return b
}
if size < minReadBufferSize {
size = minReadBufferSize
}
r := new(Reader)
r.reset(make([]byte, size), rd)
return r
}
当我使用os.Open打开一个文件时:
dictFile, err := os.Open(file)
我将把dictFile传递给:
reader := bufio.NewReader(dictFile)
我发现底层代码使用了函数NewReaderSize
,但我不理解的是rd.(*Reader)
。Reader
是包bufio
中包含的结构体类型。紧随结构体之后的星号是我从中看到的从指针Reader
获取值的方式,但它不是一个指针,所以没有意义。而且,它使用了点运算符rd.(*Reader)
,我完全困惑了。这种用法在第47行是什么意思?这是什么样的符号表示法?
英文:
// NewReaderSize returns a new Reader whose buffer has at least the specified
43 // size. If the argument io.Reader is already a Reader with large enough
44 // size, it returns the underlying Reader.
45 func NewReaderSize(rd io.Reader, size int) *Reader {
46 // Is it already a Reader?
47 b, ok := rd.(*Reader)
48 if ok && len(b.buf) >= size {
49 return b
50 }
51 if size < minReadBufferSize {
52 size = minReadBufferSize
53 }
54 r := new(Reader)
55 r.reset(make([]byte, size), rd)
56 return r
57 }
When I use os.Open to open a file
dictFile, err := os.Open(file)
I'm going to pass dicFile to
reader := bufio.NewReader(dictFile)
I found the underlying code is using func NewReaderSize
, but what I can not understand is rd.(*Reader)
. Reader
is the struct type contained in package bufio
. Asterisk followed by a struct is from what I see to get the value from pointer Reader
, but it is not a pointer, so it does not make sense. Further more, it's using dot operator rd.(*Reader)
, I totally got confused. What's the meaning of this kind of usage in line 47? What kind of notation it is?
答案1
得分: 10
你的示例中第47行的语法是类型断言,它断言接口变量的值为特定类型。在你的例子中,语句
b, ok := rd.(*Reader)
断言接口rd
的底层值为*Reader
类型(指向Reader
结构体的指针),将给你一个类型为*Reader
的b
和一个布尔值ok
,指示断言是否成功以及底层值是否真的是*Reader
类型。
以下是一个抽象的示例(play链接):
type readerA struct {}
func Read(a []byte) (int, error) {}
type readerB struct {}
func Read(a []byte) (int, error) {}
func TakesAReader(r io.Reader) {
val, ok := r.(*readerA)
fmt.Println(val, ok)
}
TakesAReader(&readerA{}) // 输出 &{}, true
TakesAReader(&readerB{}) // 输出 nil, false
所以你可以看到,类型断言只是一种提取接口所覆盖的值的方式。
英文:
The syntax in line 47 in your example is a Type Assertion, it asserts the value of interface variables to be of a specific type. Concretely in your case, the statement
b, ok := rd.(*Reader)
asserts the underlying value of the interface rd
to be of type *Reader
(a pointer to a value of struct Reader
), giving you b
of type *Reader
and a boolean value ok
that indicates whether the assertion is OK and the underlying value really is of type *Reader
.
An abstract example (play):
type readerA struct {}
func Read(a []byte) (int, error) {}
type readerB struct {}
func Read(a []byte) (int, error) {}
func TakesAReader(r io.Reader) {
val, ok := r.(*readerA)
fmt.Println(val, ok)
}
TakesAReader(&readerA{}) // prints &{}, true
TakesAReader(&readerB{}) // prints nil, false
So you see, type assertions are just a way to pull out the value that is covered by an interface.
答案2
得分: 8
newReaderSize
接受一个读取器(io.Reader
接口)并返回一个指向Reader
(在bufio
中定义的struct
)的指针。
这被称为类型断言:
b, ok := rd.(*Reader)
根据Go语言规范:
对于接口类型的表达式x和类型T,主表达式x.(T) 断言x不是nil,并且存储在x中的值是类型T。表达式x.(T)被称为类型断言。
这行代码将读取器断言为*Reader
类型,如果断言成功并且该Reader
的缓冲区足够大,它将立即返回(因为它已经是我们想要的类型)。
英文:
newReaderSize
takes a reader (io.Reader
interface) and returns a pointer to Reader
(struct
defined in bufio
).
This is called a type assertion:
b, ok := rd.(*Reader)
From golang spec:
> For an expression x of interface type and a type T, the primary
> expression x.(T) asserts that x is not nil and that the value stored
> in x is of type T. The notation x.(T) is called a type assertion.
This line is taking that reader and asserting it is a type of *Reader
, if it succeeds and that Reader
has buffer big enough its immedietly returned (because it's already what we want).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论