以下代码在类型检查那边会出错,只会执行default的。但是在简单的代码中我试验过了可以使用这种type之后的类型作为case的一种情况的
```go
type CBC func(b cipher.Block, iv []byte) cipher.BlockMode
type CFB func(b cipher.Block, iv []byte) cipher.Stream
type ModeFunc string
const (
CBCDecrypter ModeFunc = "NewCBCDecrypter"
CBCEncrypter ModeFunc = "NewCBCEncrypter"
CFBDecrypter ModeFunc = "NewCFBDecrypter"
CFBEncrypter ModeFunc = "NewCFBEncrypter"
)
//接下来就是将这两种不同模式下的aes加密写成一个函数
func AESCrypt(word, key, iv []byte, modeFunc ModeFunc) []byte {
CheckKey(key)
funcs := map[ModeFunc] interface{} {
CBCEncrypter: cipher.NewCBCEncrypter,
CBCDecrypter: cipher.NewCBCDecrypter,
CFBDecrypter: cipher.NewCFBDecrypter,
CFBEncrypter: cipher.NewCFBEncrypter,
}
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
//得先判定加密还是解密
if modeFunc == CBCEncrypter || modeFunc == CFBEncrypter {
word = PKCS7Padding(word, block.BlockSize())
}
result := make([]byte, len(word))
//bug 类型检查为什么会运行到default。。。 查到了。
//不用type类型的时候是可以识别的 但是为什么用type之后的别名识别不了呢
//查了下资料,资料显示 type和c/c++中的typedef是不一样的
//type之后产生的类型只继承了原有类型的所有元素 但是不包括函数
//所以两个类型是不对等的 其实有些奇怪为什么在上面函数中map的value类型为什么能直接使用type之后的类型而且不出问题
//而且事实上我在某个地方类型检查是使用过type类型,并没有出问题
switch fun := funcs[modeFunc].(type) {
case CBC:
blockMode := fun(block, iv)
blockMode.CryptBlocks(result, word)
case CFB:
blockMode := fun(block, iv)
blockMode.XORKeyStream(result, word)
default:
fmt.Println("something wrong!")
}
if modeFunc == CBCDecrypter || modeFunc == CFBDecrypter {
result = PKCS7UnPadding(result)
}
return result
}
```
之前我用一个简单的文件检查过这种方法能实施的,但是到这里就出错了。必须要把函数原型原封不动的写出来才能正常执行。
switch改成这样才是正确的。但是我无法理解为什么上面的方式是不对的
```go
switch fun := funcs[modeFunc].(type) {
case func(b cipher.Block, iv []byte) cipher.BlockMode:
blockMode := fun(block, iv)
blockMode.CryptBlocks(result, word)
case func(b cipher.Block, iv []byte) cipher.Stream:
blockMode := fun(block, iv)
blockMode.XORKeyStream(result, word)
default:
fmt.Println("something wrong!")
}
```
还有以下代码也是成立的,证明map的value的类型使用type之后的类型也是可以的。
```go
func AESCBCCrypt(word, key, iv []byte, modeFunc ModeFunc) []byte {
funcs := map[ModeFunc]NewCBCCipherModel{
CBCEncrypter: cipher.NewCBCEncrypter,
CBCDecrypter: cipher.NewCBCDecrypter,
}
//检查key的合法性
CheckKey(key)
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
blockSize := block.BlockSize()
//若处于加密模式,就先加补码否则在这就啥也不动
if modeFunc == CBCEncrypter {
//加上补码确保word是aes.blockSize的整倍数
word = PKCS7Padding(word, blockSize)
}
blockMode := funcs[modeFunc](block, iv)
result := make([]byte, len(word))
blockMode.CryptBlocks(result, word)
//处于解码模式的时候 结果去补码
if modeFunc == CBCDecrypter {
result = PKCS7UnPadding(result)
}
return result
}
```
我在这就搞不懂第一块代码的问题所在了,虽然能用第二种写法解决问题但是无法理解其中的错误。还望高手能够从细节方面给出简答。再次感谢!!!
![image.png](https://static.studygolang.com/181102/1dfe32aa4684b604331e2bc7eacaeb23.png)
![image.png](https://static.studygolang.com/181102/f8464eef55d40e0c8d74b9eae4c5034c.png)
#2
更多评论
go 中的type这种用法是重新定义了一个类型 type CBC func(b cipher.Block, iv []byte) cipher.BlockMode;而类型别名这个特性在golang1.9中引入,用法是type name = string;前一种就如下两个类一般,他们有相同的内部结构但类型判断时不是同一个类型。
class A{
a int;
b int;
};
class B{
a int;
b int;
};
#1