这个问题并不像我想的那么明确,我会问一个更好的问题。但是我不想在此标记重复。因此,我已提出自己的问题。如果可以,可以将其删除以免混淆社区。请只做那些需要的。当您在这里时,请不要对我投反对票。抱歉,不清楚
我是golang的新手,刚掌握了它。
我正在学习环游,然后以我自己的理解来使用它。 我当时在Interfaces并开始以自己的理解实施。 这是Go PlayGround Link
步骤1:我将3种类型分别设为int,struct和interface
package main
import (
"fmt"
)
type MyInt int
type Pair struct {
n1, n2 int
}
type twoTimeable interface {
result() (int, int)
}
第2步:然后我为指针接收器实现twoTimeable,因为它更改了基础值。
func (p *Pair) result() (int, int) {
p.n1 = 2 * p.n1
p.n2 = 2 * p.n2
return p.n1, p.n2
}
func (m *MyInt) result() (int, int) {
*m = 2 * (*m)
return int(*m), 0
}
步骤3:然后,我在主函数中声明并分配了MyInt,Pair及其对应的指针。我还声明了twoTimeable接口
mtemp := MyInt(2)
var m1 MyInt
var m2 *MyInt
var p1 Pair
var p2 *Pair
m1, m2, p1, p2 = MyInt(1), &mtemp, Pair{3, 4}, &Pair{5, 6}
var tt twoTimeable
fmt.Println(" Values : ", m1, *m2, p1, *p2, tt)
步骤4:我分配了MyInt,Pair及其指针(称为实现的方法)并打印出来。
tt = m1
fmt.Println(tt.result())
fmt.Printf("Value of m1 %v\n", m1)
tt = m2
fmt.Println(tt.result())
fmt.Printf("Value of m2 %v\n", *m2)
tt = p1
fmt.Println(tt.result())
fmt.Printf("Value of p1 %v\n", p1)
tt = p2
fmt.Println(tt.result())
fmt.Printf("Value of p2 %v\n", *p2)
显示错误:
prog.go:41:5: cannot use m1 (type MyInt) as type twoTimeable in assignment:
MyInt does not implement twoTimeable (result method has pointer receiver)
prog.go:49:5: cannot use p1 (type Pair) as type twoTimeable in assignment:
Pair does not implement twoTimeable (result method has pointer receiver)
我也读过this question,我知道m1和p1无法寻址,这就是为什么它无法编译的原因。
但是如果我使用p1或m1 p1/m1.result()
(自动取消引用FTW),方法result()就会很好地工作
现在在第2步中,将指针接收器更改为值接收器,并将* m更改为m(我知道Output的更改)
func (p Pair) result() (int, int) {
p.n1 = 2 * p.n1
p.n2 = 2 * p.n2
return p.n1, p.n2
}
func (m MyInt) result() (int, int) {
m = 2 * (m)
return int(m), 0
}
它突然不显示编译错误。不适用于m2和p2,因为现在没有使用* MyInt和* Pair
的结果实现这意味着如果接口方法实现具有值接收器,则tt可以容纳指针和值。 但是,当接口方法实现具有指针接收器时,它将无法保存非指针。
Q1:为什么可以在值接收器接口方法(p MyInt)result()上使用指针(tt = m2),而不在指针接收器接口方法(p * MyInt)result()上使用值(tt = m1)很好)。
现在,让我们返回指针接收器。
是否存在一种方法,如果函数接受参数(ttTwoTimeable),则无论tt是否为类型指针,我都可以调用tt.result(),因为result()仅由指针接收器定义。
请参见下面的代码:
func doSomething(tt twoTimeable) {
temp1, temp2 := tt.result()
fmt.Print("doing something with ", temp1, temp2)
}
由于tt可以是任何预定义的类型(指针或非指针),所以支持参数(tt * twoTimeable,如果我什至可以做到)似乎不是解决方案,或者我是否依赖函数的用户提供指针。如果我不必更改基础值,即使用值接收器,这不是问题,因为tt可以保存值或指向该值的指针
我总是接受答案。
答案 0 :(得分:0)
是否存在一种方法,如果函数接受参数(ttTwoTimeable),则无论tt是否为类型指针,我都可以调用tt.result(),因为result()仅由指针接收器定义。
这似乎是一个主要的误解。如果tt
是接口类型twoTimetable
的变量,则有一个result
方法,可以调用此方法。但是tt
的基础类型根本不是 matter 。接口类型完全封装了相关的基础类型。接口类型提供了一组方法,可以调用这些方法,而不能调用其他方法。
具体类型(例如,您的MyInt)对类型为twoInterfaces的变量的可分配性问题是一个不同 问题。如果您的具体类型(例如MyInt)碰巧具有由接口类型(此处为twoTimetables)定义的所有方法,则可以分配该类型,否则就可以分配。
问题“我的具体类型有什么方法”是第三个问题。这是唯一一个有点复杂的问题。在接收者T上定义的任何方法都是T的方法。对于指针类型* T来说,* T 上的方法和都是关于T count的方法。
答案 1 :(得分:-1)
Q1:为什么可以在值接收器方法上使用指针,但反之则不行呢?
因为语言规范说得很好:https://golang.org/ref/spec#Method_sets:
相应指针类型* T的方法集是用接收者* T或T声明的所有方法的集合(也就是说,它还包含T的方法集)。
(规格可能如下所示:方便。)
对于其余的问题:我丝毫不知道你在问什么。 $rules['checkin'] = $request->checkin;
$rules['checkout'] = $request->checkout;
$rules['cancellation_policy'] = $request->cancellation_policy;
$request->merge(['rules' => json_encode($rules)]);
的代码是完全可以的。您可以在实现do Something
方法的任何类型的result
上调用tt
。此类型是否为指针类型无关紧要。您可以从此方法调用中返回两个result() (int, int)
,并且可以使用这些int进行任何操作。
(关于“指向接口的指针”部分:是的。在技术上可以做int
。但是您从不需要这不需要。(从不。)(当然,这是一个谎言,但如果需要的话,它是如此的稀有和精致,以至于您真的不需要初学者,而一旦需要它,您就会知道如何使用它。)这里要记住一件事:永远不要做“指向接口的指针” )
答案 2 :(得分:-1)
对于m2和p2应该不是,因为现在没有使用* MyInt和* Pair的结果实现
不。您正在混淆不同的事物,并曲解了结果。
Go可让您在大多数情况下忽略指针取消引用。
type Pair struct {
n1, n2 int
}
var pp *Pair = ...
fmt.Println(pp.n1)
看到最后一行? pp
是指向Pair的指针,但无需编写(*pp).n1
。
该取消引用是自动插入的(它是C语言中->
运算符的自动变体)。
您的m2和p2只是包含指针的变量。如果需要,这些指针将被取消引用。与指针/值接收器或接口无关。