Golang 报错:接口转换错误:接口 {} 是 nil,而不是字符串。

huangapple go评论126阅读模式
英文:

Golang panic: interface conversion: interface {} is nil, not string

问题

我已经尝试创建CA配置文件、证书和私钥,我正在使用Go语言中的cfssl命令,并尝试从以下命令模拟相同的命令:

  1. cfssl gencert -initca ca-csr.json | cfssljson -bare ca

以下是我的代码片段:

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "os/exec"
  7. "github.com/cloudflare/cfssl/log"
  8. "encoding/json"
  9. "io/ioutil"
  10. "os"
  11. "github.com/cloudflare/cfssl/cli"
  12. "github.com/cloudflare/cfssl/cli/bundle"
  13. "github.com/cloudflare/cfssl/cli/certinfo"
  14. "github.com/cloudflare/cfssl/cli/gencert"
  15. "github.com/cloudflare/cfssl/cli/gencrl"
  16. "github.com/cloudflare/cfssl/cli/genkey"
  17. "github.com/cloudflare/cfssl/cli/info"
  18. "github.com/cloudflare/cfssl/cli/ocspdump"
  19. "github.com/cloudflare/cfssl/cli/ocsprefresh"
  20. "github.com/cloudflare/cfssl/cli/ocspserve"
  21. "github.com/cloudflare/cfssl/cli/ocspsign"
  22. printdefaults "github.com/cloudflare/cfssl/cli/printdefault"
  23. "github.com/cloudflare/cfssl/cli/revoke"
  24. "github.com/cloudflare/cfssl/cli/scan"
  25. "github.com/cloudflare/cfssl/cli/selfsign"
  26. "github.com/cloudflare/cfssl/cli/serve"
  27. "github.com/cloudflare/cfssl/cli/sign"
  28. "github.com/cloudflare/cfssl/cli/version"
  29. // err "github.com/hyperledger/fabric/cop/errors"
  30. "google.golang.org/grpc"
  31. )
  32. func main() {
  33. var participantFile string = "key.pem"
  34. // file, err := os.Open("conf/ca-csr.json")
  35. // if err != nil {
  36. // log.Fatalf("missing config file: %v", err)
  37. // }
  38. // defer file.Close()
  39. // s, err := ioutil.ReadAll(file)
  40. // if err != nil {
  41. // log.Fatalf("could not read config file: %v", err)
  42. // }
  43. csr := `{
  44. "CN": "admin",
  45. "key": {
  46. "algo": "rsa",
  47. "size": 2048
  48. },
  49. "names": [
  50. {
  51. "C": "US",
  52. "L": "Portland",
  53. "O": "system:masters",
  54. "OU": "Kubernetes The Hard Way",
  55. "ST": "Oregon"
  56. }
  57. ]
  58. }`
  59. //csr := string([]byte(s[:]))
  60. GenCert(csr, participantFile)
  61. }
  62. var cfsslCmds = map[string]*cli.Command{
  63. "bundle": bundle.Command,
  64. "certinfo": certinfo.Command,
  65. "sign": sign.Command,
  66. "serve": serve.Command,
  67. "version": version.Command,
  68. "genkey": genkey.Command,
  69. "gencert": gencert.Command,
  70. "gencrl": gencrl.Command,
  71. "ocspdump": ocspdump.Command,
  72. "ocsprefresh": ocsprefresh.Command,
  73. "ocspsign": ocspsign.Command,
  74. "ocspserve": ocspserve.Command,
  75. "selfsign": selfsign.Command,
  76. "scan": scan.Command,
  77. "info": info.Command,
  78. "print-defaults": printdefaults.Command,
  79. "revoke": revoke.Command,
  80. }
  81. // CertMgr is the default certificate manager
  82. type CertMgr struct {
  83. rootPath string
  84. participantFilePath string
  85. cert []byte
  86. grpcServer *grpc.Server
  87. }
  88. type output struct {
  89. Cert string
  90. }
  91. type gencertOutput struct {
  92. cert []byte
  93. csr []byte
  94. key []byte
  95. }
  96. func GenCert(csr string, participantFile string) {
  97. var args []string
  98. gencertCmd := cfsslCmds["gencert"]
  99. var c cli.Config
  100. c.IsCA = true
  101. args = append(args, csr)
  102. out := ExecuteCommand(args, gencertCmd, c)
  103. var gencertOut map[string]interface{}
  104. json.Unmarshal([]byte(out), &gencertOut)
  105. var writeJSON output
  106. writeJSON.Cert = gencertOut["cert"].(string)
  107. jsonOut, _ := json.Marshal(writeJSON)
  108. ioutil.WriteFile(participantFile, jsonOut, 0644)
  109. return
  110. }
  111. func ExecuteCommand(args []string, command *cli.Command, c cli.Config) string {
  112. cfsslJSONCmd := exec.Command("cfssljson", "-bare")
  113. old := os.Stdout
  114. r, w, _ := os.Pipe()
  115. os.Stdout = w
  116. err := command.Main(args, c) // Execute command
  117. if err != nil {
  118. log.Error(err)
  119. }
  120. outC := make(chan string)
  121. // copy the output in a separate goroutine so printing can't block indefinitely
  122. var buf bytes.Buffer
  123. go func() {
  124. io.Copy(&buf, r)
  125. cfsslJSONCmd.Stdin = &buf
  126. outC <- buf.String()
  127. }()
  128. w.Close()
  129. out := <-outC
  130. outByte := []byte(out)
  131. tmpFile, _ := ioutil.TempFile("", "tmp")
  132. defer os.Remove(tmpFile.Name())
  133. if _, err = tmpFile.Write(outByte); err != nil {
  134. fmt.Println("err: ", err)
  135. }
  136. os.Stdin = tmpFile
  137. os.Stdout = old // restoring the real stdout
  138. err = cfsslJSONCmd.Run() // Execute cfssljson -bare <prefix>
  139. if err != nil {
  140. log.Error(err)
  141. }
  142. return out // To be used to store in participant file
  143. }

我得到了以下错误:

  1. [ERROR] open {
  2. "CN": "admin",
  3. "key": {
  4. "algo": "rsa",
  5. "size": 2048
  6. },
  7. "names": [
  8. {
  9. "C": "US",
  10. "L": "Portland",
  11. "O": "system:masters",
  12. "OU": "Kubernetes The Hard Way",
  13. "ST": "Oregon"
  14. }
  15. ]
  16. }: no such file or directory
  17. 2022/03/25 19:23:39 [ERROR] exit status 1
  18. panic: interface conversion: interface {} is nil, not string
  19. goroutine 1 [running]:
  20. main.GenCert({0xb9179c, 0xda}, {0xb3a3f3, 0x7})
  21. /home/Documents/git-repo/kunets-vpc-test/main.go:126 +0x229
  22. main.main()
  23. /home/Documents/git-repo/kunets-vpc-test/main.go:70 +0x31
  24. 任何帮助和建议将不胜感激,非常感谢!
  25. <details>
  26. <summary>英文:</summary>
  27. I have tried to create CA configuration file, certificate and private key, I am using `cfssl` command in go and try to simulate same command from
  28. cfssl gencert -initca ca-csr.json | cfssljson -bare ca
  29. Here is my code snipped
  30. package main
  31. import (
  32. &quot;bytes&quot;
  33. &quot;fmt&quot;
  34. &quot;io&quot;
  35. &quot;os/exec&quot;
  36. &quot;github.com/cloudflare/cfssl/log&quot;
  37. &quot;encoding/json&quot;
  38. &quot;io/ioutil&quot;
  39. &quot;os&quot;
  40. &quot;github.com/cloudflare/cfssl/cli&quot;
  41. &quot;github.com/cloudflare/cfssl/cli/bundle&quot;
  42. &quot;github.com/cloudflare/cfssl/cli/certinfo&quot;
  43. &quot;github.com/cloudflare/cfssl/cli/gencert&quot;
  44. &quot;github.com/cloudflare/cfssl/cli/gencrl&quot;
  45. &quot;github.com/cloudflare/cfssl/cli/genkey&quot;
  46. &quot;github.com/cloudflare/cfssl/cli/info&quot;
  47. &quot;github.com/cloudflare/cfssl/cli/ocspdump&quot;
  48. &quot;github.com/cloudflare/cfssl/cli/ocsprefresh&quot;
  49. &quot;github.com/cloudflare/cfssl/cli/ocspserve&quot;
  50. &quot;github.com/cloudflare/cfssl/cli/ocspsign&quot;
  51. printdefaults &quot;github.com/cloudflare/cfssl/cli/printdefault&quot;
  52. &quot;github.com/cloudflare/cfssl/cli/revoke&quot;
  53. &quot;github.com/cloudflare/cfssl/cli/scan&quot;
  54. &quot;github.com/cloudflare/cfssl/cli/selfsign&quot;
  55. &quot;github.com/cloudflare/cfssl/cli/serve&quot;
  56. &quot;github.com/cloudflare/cfssl/cli/sign&quot;
  57. &quot;github.com/cloudflare/cfssl/cli/version&quot;
  58. // err &quot;github.com/hyperledger/fabric/cop/errors&quot;
  59. &quot;google.golang.org/grpc&quot;
  60. )
  61. func main() {
  62. var participantFile string = &quot;key.pem&quot;
  63. // file, err := os.Open(&quot;conf/ca-csr.json&quot;)
  64. // if err != nil {
  65. // log.Fatalf(&quot;missing config file: %v&quot;, err)
  66. // }
  67. // defer file.Close()
  68. // s, err := ioutil.ReadAll(file)
  69. // if err != nil {
  70. // log.Fatalf(&quot;could not read config file: %v&quot;, err)
  71. // }
  72. csr := `{
  73. &quot;CN&quot;: &quot;admin&quot;,
  74. &quot;key&quot;: {
  75. &quot;algo&quot;: &quot;rsa&quot;,
  76. &quot;size&quot;: 2048
  77. },
  78. &quot;names&quot;: [
  79. {
  80. &quot;C&quot;: &quot;US&quot;,
  81. &quot;L&quot;: &quot;Portland&quot;,
  82. &quot;O&quot;: &quot;system:masters&quot;,
  83. &quot;OU&quot;: &quot;Kubernetes The Hard Way&quot;,
  84. &quot;ST&quot;: &quot;Oregon&quot;
  85. }
  86. ]
  87. }`
  88. //csr := string([]byte(s[:]))
  89. GenCert(csr, participantFile)
  90. }
  91. var cfsslCmds = map[string]*cli.Command{
  92. &quot;bundle&quot;: bundle.Command,
  93. &quot;certinfo&quot;: certinfo.Command,
  94. &quot;sign&quot;: sign.Command,
  95. &quot;serve&quot;: serve.Command,
  96. &quot;version&quot;: version.Command,
  97. &quot;genkey&quot;: genkey.Command,
  98. &quot;gencert&quot;: gencert.Command,
  99. &quot;gencrl&quot;: gencrl.Command,
  100. &quot;ocspdump&quot;: ocspdump.Command,
  101. &quot;ocsprefresh&quot;: ocsprefresh.Command,
  102. &quot;ocspsign&quot;: ocspsign.Command,
  103. &quot;ocspserve&quot;: ocspserve.Command,
  104. &quot;selfsign&quot;: selfsign.Command,
  105. &quot;scan&quot;: scan.Command,
  106. &quot;info&quot;: info.Command,
  107. &quot;print-defaults&quot;: printdefaults.Command,
  108. &quot;revoke&quot;: revoke.Command,
  109. }
  110. // CertMgr is the default certificate manager
  111. type CertMgr struct {
  112. rootPath string
  113. participantFilePath string
  114. cert []byte
  115. grpcServer *grpc.Server
  116. }
  117. type output struct {
  118. Cert string
  119. }
  120. type gencertOutput struct {
  121. cert []byte
  122. csr []byte
  123. key []byte
  124. }
  125. func GenCert(csr string, participantFile string) {
  126. var args []string
  127. gencertCmd := cfsslCmds[&quot;gencert&quot;]
  128. var c cli.Config
  129. c.IsCA = true
  130. args = append(args, csr)
  131. out := ExecuteCommand(args, gencertCmd, c)
  132. var gencertOut map[string]interface{}
  133. json.Unmarshal([]byte(out), &amp;gencertOut)
  134. var writeJSON output
  135. writeJSON.Cert = gencertOut[&quot;cert&quot;].(string)
  136. jsonOut, _ := json.Marshal(writeJSON)
  137. ioutil.WriteFile(participantFile, jsonOut, 0644)
  138. return
  139. }
  140. func ExecuteCommand(args []string, command *cli.Command, c cli.Config) string {
  141. cfsslJSONCmd := exec.Command(&quot;cfssljson&quot;, &quot;-bare&quot;)
  142. old := os.Stdout
  143. r, w, _ := os.Pipe()
  144. os.Stdout = w
  145. err := command.Main(args, c) // Execute command
  146. if err != nil {
  147. log.Error(err)
  148. }
  149. outC := make(chan string)
  150. // copy the output in a separate goroutine so printing can&#39;t block indefinitely
  151. var buf bytes.Buffer
  152. go func() {
  153. io.Copy(&amp;buf, r)
  154. cfsslJSONCmd.Stdin = &amp;buf
  155. outC &lt;- buf.String()
  156. }()
  157. w.Close()
  158. out := &lt;-outC
  159. outByte := []byte(out)
  160. tmpFile, _ := ioutil.TempFile(&quot;&quot;, &quot;tmp&quot;)
  161. defer os.Remove(tmpFile.Name())
  162. if _, err = tmpFile.Write(outByte); err != nil {
  163. fmt.Println(&quot;err: &quot;, err)
  164. }
  165. os.Stdin = tmpFile
  166. os.Stdout = old // restoring the real stdout
  167. err = cfsslJSONCmd.Run() // Execute cfssljson -bare &lt;prefix&gt;
  168. if err != nil {
  169. log.Error(err)
  170. }
  171. return out // To be used to store in participant file
  172. }
  173. and I am getting that error
  174. [ERROR] open {
  175. &quot;CN&quot;: &quot;admin&quot;,
  176. &quot;key&quot;: {
  177. &quot;algo&quot;: &quot;rsa&quot;,
  178. &quot;size&quot;: 2048
  179. },
  180. &quot;names&quot;: [
  181. {
  182. &quot;C&quot;: &quot;US&quot;,
  183. &quot;L&quot;: &quot;Portland&quot;,
  184. &quot;O&quot;: &quot;system:masters&quot;,
  185. &quot;OU&quot;: &quot;Kubernetes The Hard Way&quot;,
  186. &quot;ST&quot;: &quot;Oregon&quot;
  187. }
  188. ]
  189. }: no such file or directory
  190. 2022/03/25 19:23:39 [ERROR] exit status 1
  191. panic: interface conversion: interface {} is nil, not string
  192. goroutine 1 [running]:
  193. main.GenCert({0xb9179c, 0xda}, {0xb3a3f3, 0x7})
  194. /home/Documents/git-repo/kunets-vpc-test/main.go:126 +0x229
  195. main.main()
  196. /home/Documents/git-repo/kunets-vpc-test/main.go:70 +0x31
  197. Any help advice would be appreciated, thank you very much!
  198. </details>
  199. # 答案1
  200. **得分**: 4
  201. 我认为你在 goroutine 运行时关闭了 w,并且以某种方式突然结束了进程或读取命令输出。尝试通过打印 "out" 来确认,如果是这个问题,可以使用 defer 关闭 w
  202. 使用安全转换来避免 panic,并使用 spew.Dump(需要外部库)来检查数据。
  203. 或者使用调试器。
  204. ```go
  205. variable, ok := something.(string)
  206. if !ok {
  207. // 无法转换为字符串,现在该怎么办???
  208. }
英文:

I think you are closing the w while the goroutine is running and somehow it ends abruptly the process or reading the command output. Try confirm by print the “out” and if it is the issue, close w with defer

Use a safe convertion to avoid panic and use spew.Dump (need external library) to inspect the data.

Or use a debugger

  1. variable, ok := something.(string)
  2. if !ok {
  3. // cant convert to string, now what???
  4. }
  5. </details>
  6. # 答案2
  7. **得分**: 0
  8. 我在模拟时遇到了类似的问题
  9. ```go
  10. type MockSomethingRepository struct {
  11. mock.Mock
  12. }
  13. func (msr *MockSomethingRepository) FindById(id string) (*entity.Session, error) {
  14. args := msr.Called(id)
  15. return args.Get(0).(*entity.Session), args.Error(1)
  16. }

然后我尝试像这样使用模拟对象:

  1. mockSomethignRepository.On("FindById", "1").Return(nil, fmt.Errorf("something went wrong"))

我得到了类似的错误interface conversion: interface {} is *[]entity.Session, not []entity.Session

我在https://go.dev/play/p/CLyY2y9-2VF找到了解决方案,所以我通过以下方式解决了问题:

  1. type MockSomethingRepository struct {
  2. mock.Mock
  3. }
  4. func (msr *MockSomethingRepository) FindById(id string) (*entity.Session, error) {
  5. args := msr.Called(id)
  6. if args.Error(1) != nil {
  7. return nil, args.Error(1)
  8. }
  9. return args.Get(0).(*entity.Session), args.Error(1)
  10. }

我没有解释,但它有效!

英文:

I was struggling with a similar problem when I was mocking.

  1. type MockSomethingRepository struct {
  2. mock.Mock
  3. }
  4. func (msr *MockSomethingRepository) FindById(id string) (*entity.Session, error) {
  5. args := msr.Called(id)
  6. return args.Get(0).(*entity.Session), args.Error(1)
  7. }

and Then I tried to use the mock like this

  1. mockSomethignRepository.On(&quot;FindById&quot;, &quot;1&quot;).Return(nil, fmt.Errorf(&quot;something went wrong&quot;))

I got similar error nterface conversion: interface {} is *[]entity.Session, not []entity.Session

I have found solution in https://go.dev/play/p/CLyY2y9-2VF
so I have solved it by

  1. type MockSomethingRepository struct {
  2. mock.Mock
  3. }
  4. func (msr *MockSomethingRepository) FindById(id string) (*entity.Session, error) {
  5. args := msr.Called(id)
  6. if args.Error(1) != nil {
  7. return nil, args.Error(1)
  8. }
  9. return args.Get(0).(*entity.Session), args.Error(1)
  10. }

I don't have an explanation but It works!

huangapple
  • 本文由 发表于 2022年3月26日 03:54:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/71622424.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定