var _ I = (*T)(nil)

var _ I = (*T)(nil)

在Go语言中,没有设计的" 实现 "声明.要求编译器通过尝试赋值来检查类型T是否实现接口I的唯一方法(是的,虚拟的:).注意,Go lang区分结构和指针上声明的方法,在赋值检查中使用正确的方法!

type T struct{}
var _ I = T{}       // Verify that T implements I.
var _ I = (*T)(nil) // Verify that *T implements I.

如何保证我的类型满足接口?
您可以要求编译器检查该类型是否T实现了接口,方法I是尝试使用 0 值T或指向 的指针T(视情况而定)。
我们可以用一个例子来说明这一点:

package main

type I interface{ M() }
type T struct{}

func (T) M() {}

//func (*T) M() {} //var _ I = T{}: T does not implement I (M method has pointer receiver)
// 如果T(或*T,相应地)没有实现I,错误将在编译时被捕获。请参阅接口实现中的非接口方法。

func main() {
  //avoids allocation of memory
  var _ I = T{}       // Verify that T implements I.
  var _ I = (*T)(nil) // Verify that *T implements I.
  //allocation of memory
  var _ I = &T{}      // Verify that &T implements I.
  var _ I = new(T)    // Verify that new(T) implements I.
}

通常,如果您不知道某个值的类型,则检查该值是否实现了接口。如果已知,则检查由编译器自动完成。

*Go &T{}和new(T)和(T)(nil)区别

  • (* T)(nil) 它返回nil指针或没有指针,但仍然为struct的所有字段分配内存。
  • new(T)和& T {} 完全等价:分配一个零T并返回一个指向这个分配的内存的指针。唯一的区别是,& T {} 不适用于内置类型,如 int ;你只能做 new(int)。
package main
 
import (
	"fmt"
)
 
type Struct struct {
	Field int
}
 
func main() {
	test1 := &Struct{}
	test2 := new(Struct)
	test3 := (*Struct)(nil)
	fmt.Printf("%#v, %#v, %#v \n", test1, test2, test3) //&main.Struct{Field:0}, &main.Struct{Field:0}, (*main.Struct)(nil)
 
	fmt.Printf("%T, %T, %T \n", test1, test2, test3) // *main.Struct, *main.Struct, *main.Struct
 
	test1.Field = 1
	fmt.Println(test1.Field) // 1
 
	test2.Field = 2
	fmt.Println(test2.Field) // 2
 
	test3.Field = 3    // test3分配内存,返回一个nil指针,不能使用     
	// fmt.Println(test3.Field)
}

参考:https://qa.1r1g.com/sf/
https://blog.csdn.net/weixin_40580582/article/details/118686221?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-1-118686221-blog-129443153.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-1-118686221-blog-129443153.pc_relevant_default&utm_relevant_index=1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
package main import ( "flag" "fmt" "os" ) const ( S = 54 // standard size of bmp headers T = 32 // number of bytes needed to hide the text length C = 4 // number of bytes needed to hide a character ) // modify hides an integer to a byte slice func modify(value int, pix []byte, size int) { for i := 0; i < size; i++ { pix[i] = (pix[i] & 0xFC) | byte(value&0x03) value >>= 2 } // TODO: write your code here // replace last 2 bits of pix[i] with the last 2 bits of value // the next iteration repeats with the next 2 bits of value } var ( srcImage string // input image name srcTxt string // input text name destImage string // output doctored image name ) // init sets command line arguments func init() { // DON'T modify this function!!! flag.StringVar(&srcImage, "i", "", "input image name") flag.StringVar(&srcTxt, "t", "", "input text name") flag.StringVar(&destImage, "d", "", "output doctored image name") } func main() { // parse command line arguments flag.Parse() if srcImage == "" || srcTxt == "" || destImage == "" { flag.PrintDefaults() os.Exit(1) } // read input image to a byte slice p p, err := os.ReadFile(srcImage) if err != nil { fmt.Printf("Read image file failed, err = %v\n", err) os.Exit(1) } // read input text to a byte slice t t, err := os.ReadFile(srcTxt) if err != nil { fmt.Printf("Read text file failed, err = %v\n", err) os.Exit(1) } // check if the text is too big if T+len(t)*C > len(p[S:]) { fmt.Println("The text file is too big") os.Exit(1) } // save the text length to p modify(len(t), p[S:S+T], T) // save the content of text to p for i := 0; i < len(t); i++ { offset := S + T + C*i modify(int(t[i]), p[offset:offset+C], C) } // write the modified p to destImage err = os.WriteFile(destImage, p, 0644) if err != nil { fmt.Printf("Write doctored image failed, err = %v\n", err) os.Exit(1) } }这是一个将文字隐藏到图片中的代码,请帮我讲下面这个恢复文字的代码完善package main import ( "flag" "os" "fmt" ) const ( S = 54 // standard size of header T = 32 // number of bytes needed to hide the text length C = 4 // number of bytes needed to hide a character ) func modify(pix []byte, value int, size int){ for i := size-1; i >= 0; i-- { value = int((pix[i] & 0x03) | byte(value&0xFC)) value <<= 2 } } var ( image string // input doctor image name txt string // output text name ) // init sets command line arguments func init() { // DON'T modify this function!!! flag.StringVar(&image, "i", "", "input image name") flag.StringVar(&txt, "t", "", "output text name") } func main() { // parse command line arguments flag.Parse() if image == "" || txt == "" { flag.PrintDefaults() os.Exit(1) } p, err := os.ReadFile(image) if err != nil { fmt.Printf("Read image file failed, err = %v\n", err) os.Exit(1) } modify(p[S:S+T], len(o), T) for i := len(o)-1; i >= 0; i-- { offset := S + T + C*i modify(p[offset:offset+C], int(o[i]) , C) } err = os.WriteFile(txt, o, 0644) if err != nil { fmt.Printf("Write doctored image failed, err = %v\n", err) os.Exit(1) } }
05-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值