嘟嘟社区

[疑问] 求助,go代码error: invalid memory address or nil pointer dereference


本帖最后由 魔鬼筋肉人 于 2022-4-12 23:32 编辑

再次根据老哥提示加了return跳出错误,但是又提示fatal error: all goroutines are asleep – deadlock!
好难搞,对于我这种只会css的人来说
                                                if err != nil {
                                                        return
}

——————————
根据楼层老哥的提示,修改后定位到出错的图片
提示“invalid JPEG format: short Huffman data ”
但是查看图片是可以显示的,暂时不知道怎么解决,我再继续搜索看看,谢谢各位老哥!

—————-
求助,运行提示下面的错误
搜一天了没找到适合的办法

  1. PS D:img> go run composite_img.go
  2. panic: runtime error: invalid memory address or nil pointer dereference
  3. [signal 0xc0000005 code=0x0 addr=0x20 pc=0x2d3415]
  4. goroutine 57 [running]:
  5. main.main.func1.1()
  6.         D:/img/composite_img.go:142 +0x95
  7. created by main.main.func1
  8.         D:/img/composite_img.go:137 +0x225
  9. exit status 2

复制代码

  1. package main
  2. import (
  3.         _ "embed"
  4.         "fmt"
  5.         "github.com/fogleman/gg"
  6.         "github.com/golang/freetype/truetype"
  7.         "github.com/spf13/viper"
  8.         "image"
  9.         "image/color"
  10.         "image/jpeg"
  11.         "io/ioutil"
  12.         "os"
  13.         "path"
  14.         "path/filepath"
  15.         "strings"
  16.         "sync"
  17.         "time"
  18.         "zip2excel/pkg"
  19. )
  20. type ImgInfoList struct {
  21.         Path    string
  22.         ImgInfo []ImgInfo
  23. }
  24. type ImgInfo struct {
  25.         Path   string
  26.         Size   int64
  27.         Name   string
  28.         Suffix string
  29. }
  30. type taskInfo struct {
  31.         Path string
  32.         Name string
  33.         X    int
  34.         Y    int
  35. }
  36. type imgDraw struct {
  37.         Im         image.Image
  38.         X          int
  39.         Y          int
  40.         StringX    float64
  41.         StringY    float64
  42.         StringText string
  43. }
  44. type Config struct {
  45.         ImgFormat        []string
  46.         CompositeDir     string
  47.         CompositeLineNum int
  48. }
  49. var config = new(Config)
  50. //go:embed f.ttf
  51. var ttf []byte
  52. func init() {
  53.         viper.SetConfigType("toml")
  54.         viper.SetConfigName("config")
  55.         viper.AddConfigPath("./")
  56.         configFile := "./config.toml"
  57.         if err := viper.ReadInConfig(); err != nil {
  58.                 if _, ok := err.(viper.ConfigFileNotFoundError); ok {
  59.                         if err := os.MkdirAll(filepath.Dir(configFile), 0766); err != nil {
  60.                                 panic(err)
  61.                         }
  62.                         f, err := os.Create(configFile)
  63.                         if err != nil {
  64.                                 panic(err)
  65.                         }
  66.                         defer f.Close()
  67.                         if err := viper.WriteConfig(); err != nil {
  68.                                 panic(err)
  69.                         }
  70.                 } else {
  71.                         panic(err)
  72.                 }
  73.         }
  74.         if err := viper.Unmarshal(config); err != nil {
  75.                 panic(err)
  76.         }
  77. }
  78. func main() {
  79.         loadStart := time.Now()
  80.         const NX = 115
  81.         const NY = 75
  82.         const NXInterval = 30
  83.         const NYInterval = 100
  84.         strMaxWidth := 115 / 13
  85.         imgListArr := getImgList(config.CompositeDir)
  86.         for _, imgInfoList := range imgListArr {
  87.                 var lineNum = config.CompositeLineNum
  88.                 imgList := imgInfoList.ImgInfo
  89.                 dir := imgInfoList.Path
  90.                 //fmt.Printf("n1 的类型 %T", n1)
  91.                 filename := dir + "/" +"composite.jpeg"
  92.                 //fmt.Println("filename",filename)
  93.                 _, err := os.Stat(filename)          // 通过获取文件信息进行判断
  94.                 if err != nil {
  95.                         //fmt.Println("不存在")
  96.                 } else {
  97.                         continue
  98.                 }
  99.                 imgNum := len(imgList)
  100.                 columnNum := imgNum / lineNum
  101.                 if imgNum%lineNum != 0 {
  102.                         columnNum++
  103.                 }
  104.                 if imgNum < lineNum {
  105.                         lineNum = imgNum
  106.                 }
  107.                 //fmt.Println(lineNum, columnNum)
  108.                 dc := gg.NewContext(lineNum*(NX+NXInterval)-NXInterval, columnNum*(NY+NYInterval))
  109.                 dc.SetColor(color.RGBA{R: 39, G: 39, B: 39, A: 255})
  110.                 dc.Clear()
  111.                 ttfFont, _ := truetype.Parse(ttf)
  112.                 face := truetype.NewFace(ttfFont, &truetype.Options{
  113.                         Size: 13,
  114.                 })
  115.                 dc.SetFontFace(face)
  116.                 dc.SetColor(color.RGBA{R: 194, G: 194, B: 194, A: 255})
  117.                 imgI := 0
  118.                 var wg sync.WaitGroup
  119.                 taskChan := make(chan taskInfo, 10)
  120.                 imgChan := make(chan imgDraw, 10)
  121.                 taskSuccessChan := make(chan bool, 10)
  122.                 go func() {
  123.                         for {
  124.                                 select {
  125.                                 case info := <-taskChan:
  126.                                         go func() {
  127.                                                 defer wg.Done()
  128.                                                 var x, y int
  129.                                                
  130.                                                 im, _ := gg.LoadImage(info.Path)
  131.                                                 if im.Bounds().Size().X < im.Bounds().Size().Y {
  132.                                                         im = ScaleImage(im, NY, NX)
  133.                                                         x, y = info.X*(NX+NXInterval)+(NX-NY)/2, info.Y*(NY+NYInterval)
  134.                                                 } else {
  135.                                                         im = ScaleImage(im, NX, NY)
  136.                                                         x, y = info.X*(NX+NXInterval), info.Y*(NY+NYInterval)+(NX-NY)/2
  137.                                                 }
  138.                                                 imgChan <- imgDraw{
  139.                                                         Im:         im,
  140.                                                         X:          x,
  141.                                                         Y:          y,
  142.                                                         StringX:    float64(info.X * (NX + NXInterval)),
  143.                                                         StringY:    float64(info.Y*(NY+NYInterval) + NY + 58),
  144.                                                         StringText: info.Name,
  145.                                                 }
  146.                                                 <-taskSuccessChan
  147.                                         }()
  148.                                 case imgDrawInfo := <-imgChan:
  149.                                         dc.DrawImage(imgDrawInfo.Im, imgDrawInfo.X, imgDrawInfo.Y)
  150.                                         str := getString(imgDrawInfo.StringText, strMaxWidth*2-1)
  151.                                         dc.DrawStringWrapped(str, imgDrawInfo.StringX, imgDrawInfo.StringY, 0, 0, NX, 0, gg.AlignCenter)
  152.                                         wg.Done()
  153.                                 }
  154.                         }
  155.                 }()
  156.                 for y := 0; y < columnNum; y++ {
  157.                         if imgI >= imgNum {
  158.                                 break
  159.                         }
  160.                         for x := 0; x < lineNum; x++ {
  161.                                 if imgI >= imgNum {
  162.                                         break
  163.                                 }
  164.                                 taskChan <- taskInfo{
  165.                                         Path: imgList[imgI].Path + "/" + imgList[imgI].Name,
  166.                                         Name: imgList[imgI].Name,
  167.                                         X:    x,
  168.                                         Y:    y,
  169.                                 }
  170.                                 taskSuccessChan <- true
  171.                                 wg.Add(2)
  172.                                 imgI++
  173.                         }
  174.                 }
  175.                 wg.Wait()
  176.                 im := dc.Image()
  177.                 f, err := os.Create(dir + "/composite.jpeg")
  178.                 if err != nil {
  179.                         panic(err)
  180.                 }
  181.                 jpeg.Encode(f, im, nil)
  182.                 fileName := strings.Replace(dir,".\操作区", "", -1)
  183.                 defer func() {
  184.                         fmt.Println("缩略图生成耗时: ",time.Now().Sub(loadStart).Seconds(),"ms  ",fileName)
  185.                 }()
  186.         }
  187. }
  188. func getString(str string, maxLen int) string {
  189.         text := ""
  190.         w := 0
  191.         strSize := 0
  192.         for _, c := range []rune(str) {
  193.                 if pkg.IsHalfwidth(c) {
  194.                         strSize = 1
  195.                 } else {
  196.                         strSize = 2
  197.                 }
  198.                 w += strSize
  199.                 if w >= maxLen {
  200.                         text += "…"
  201.                         break
  202.                 }
  203.                 text += string(c)
  204.         }
  205.         return text
  206. }
  207. // ScaleImage 缩放图片
  208. func ScaleImage(image image.Image, x, y int) image.Image {
  209.         //loadStart := time.Now()
  210. /*         defer func() {
  211.                 fmt.Printf("缩放耗时: %vn", time.Now().Sub(loadStart).Seconds())
  212.         }() */
  213.         w := image.Bounds().Size().X
  214.         h := image.Bounds().Size().Y
  215.         dc := gg.NewContext(x, y)
  216.         var ax = float64(x) / float64(w)
  217.         var ay = float64(y) / float64(h)
  218.         dc.Scale(ax, ay)
  219.         dc.DrawImage(image, 0, 0)
  220.         return dc.Image()
  221. }
  222. func getImgList(p string) (imgInfoListArr []ImgInfoList) {
  223.         files, _ := ioutil.ReadDir(p)
  224.         var imgInfoList ImgInfoList
  225.         imgInfoList.Path = p
  226.         for _, file := range files {
  227.                 if !file.IsDir() {
  228.                         fileName := file.Name()
  229.                         fileSuffix := strings.ToLower(path.Ext(fileName))
  230.                         if pkg.StringsContains(config.ImgFormat, fileSuffix) {
  231.                                 imgInfoList.ImgInfo = append(imgInfoList.ImgInfo, ImgInfo{
  232.                                         Path:   p,
  233.                                         Size:   file.Size(),
  234.                                         Name:   fileName,
  235.                                         Suffix: fileSuffix,
  236.                                 })
  237.                         }
  238.                 } else {
  239.                         imgInfoListArr = append(imgInfoListArr, getImgList(p+"/"+file.Name())…)
  240.                 }
  241.         }
  242.         if len(imgInfoList.ImgInfo) > 10 {
  243.                 imgInfoListArr = append(imgInfoListArr, imgInfoList)
  244.         }
  245.         return imgInfoListArr
  246. }

复制代码

这里99%以上的人看不懂这个,看得懂的1%,也不愿意去帮人免费debug这东西。
im, _ := gg.LoadImage(info.Path)
                                                if im.Bounds().Size().X < im.Bounds().Size().Y {

LoadImage返回的第二个参数判断一下啊,假如有error,那么im就是nil,你直接操作空的im当然会报错了

errlang别随便不处理error啊
在第 141, 142 行之间插入:
  1. im, err := gg.LoadImage(info.Path)
  2. if err != nil {
  3.     log.Printf("LoadImage(%s) error: %v", info.Path, err)
  4. }

复制代码

同三楼五楼,go代码最大特色就是满屏幕的 if err。你这个代码竟然没看到有几个,程序崩是迟早的。
本帖最后由 魔鬼筋肉人 于 2022-4-12 22:59 编辑

whiler 发表于 2022-4-12 22:44
在第 141, 142 行之间插入:

谢谢老哥 还是会出错,我插入了
“invalid JPEG format: short Huffman data ”

  1. panic: runtime error: invalid memory address or nil pointer dereference
  2. [signal 0xc0000005 code=0x0 addr=0x20 pc=0x89355c]
  3. goroutine 115 [running]:
  4. main.main.func1.1()
  5.         D:/img/composite_img.go:145 +0x13c
  6. created by main.main.func1
  7.         D:/img/composite_img.go:138 +0x225
  8. exit status 2

复制代码

  1. package main
  2. import (
  3.         _ "embed"
  4.         "fmt"
  5.         "github.com/fogleman/gg"
  6.         "github.com/golang/freetype/truetype"
  7.         "github.com/spf13/viper"
  8.         "image"
  9.         "image/color"
  10.         "image/jpeg"
  11.         "io/ioutil"
  12.         "os"
  13.         "log"
  14.         "path"
  15.         "path/filepath"
  16.         "strings"
  17.         "sync"
  18.         "time"
  19.         "zip2excel/pkg"
  20. )
  21. type ImgInfoList struct {
  22.         Path    string
  23.         ImgInfo []ImgInfo
  24. }
  25. type ImgInfo struct {
  26.         Path   string
  27.         Size   int64
  28.         Name   string
  29.         Suffix string
  30. }
  31. type taskInfo struct {
  32.         Path string
  33.         Name string
  34.         X    int
  35.         Y    int
  36. }
  37. type imgDraw struct {
  38.         Im         image.Image
  39.         X          int
  40.         Y          int
  41.         StringX    float64
  42.         StringY    float64
  43.         StringText string
  44. }
  45. type Config struct {
  46.         ImgFormat        []string
  47.         CompositeDir     string
  48.         CompositeLineNum int
  49. }
  50. var config = new(Config)
  51. //go:embed f.ttf
  52. var ttf []byte
  53. func init() {
  54.         viper.SetConfigType("toml")
  55.         viper.SetConfigName("config")
  56.         viper.AddConfigPath("./")
  57.         configFile := "./config.toml"
  58.         if err := viper.ReadInConfig(); err != nil {
  59.                 if _, ok := err.(viper.ConfigFileNotFoundError); ok {
  60.                         if err := os.MkdirAll(filepath.Dir(configFile), 0766); err != nil {
  61.                                 panic(err)
  62.                         }
  63.                         f, err := os.Create(configFile)
  64.                         if err != nil {
  65.                                 panic(err)
  66.                         }
  67.                         defer f.Close()
  68.                         if err := viper.WriteConfig(); err != nil {
  69.                                 panic(err)
  70.                         }
  71.                 } else {
  72.                         panic(err)
  73.                 }
  74.         }
  75.         if err := viper.Unmarshal(config); err != nil {
  76.                 panic(err)
  77.         }
  78. }
  79. func main() {
  80.         loadStart := time.Now()
  81.         const NX = 115
  82.         const NY = 75
  83.         const NXInterval = 30
  84.         const NYInterval = 100
  85.         strMaxWidth := 115 / 13
  86.         imgListArr := getImgList(config.CompositeDir)
  87.         for _, imgInfoList := range imgListArr {
  88.                 var lineNum = config.CompositeLineNum
  89.                 imgList := imgInfoList.ImgInfo
  90.                 dir := imgInfoList.Path
  91.                 //fmt.Printf("n1 的类型 %T", n1)
  92.                 filename := dir + "/" +"composite.jpeg"
  93.                 //fmt.Println("filename",filename)
  94.                 _, err := os.Stat(filename)          // 通过获取文件信息进行判断
  95.                 if err != nil {
  96.                         //fmt.Println("不存在")
  97.                 } else {
  98.                         continue
  99.                 }
  100.                 imgNum := len(imgList)
  101.                 columnNum := imgNum / lineNum
  102.                 if imgNum%lineNum != 0 {
  103.                         columnNum++
  104.                 }
  105.                 if imgNum < lineNum {
  106.                         lineNum = imgNum
  107.                 }
  108.                 //fmt.Println(lineNum, columnNum)
  109.                 dc := gg.NewContext(lineNum*(NX+NXInterval)-NXInterval, columnNum*(NY+NYInterval))
  110.                 dc.SetColor(color.RGBA{R: 39, G: 39, B: 39, A: 255})
  111.                 dc.Clear()
  112.                 ttfFont, _ := truetype.Parse(ttf)
  113.                 face := truetype.NewFace(ttfFont, &truetype.Options{
  114.                         Size: 13,
  115.                 })
  116.                 dc.SetFontFace(face)
  117.                 dc.SetColor(color.RGBA{R: 194, G: 194, B: 194, A: 255})
  118.                 imgI := 0
  119.                 var wg sync.WaitGroup
  120.                 taskChan := make(chan taskInfo, 10)
  121.                 imgChan := make(chan imgDraw, 10)
  122.                 taskSuccessChan := make(chan bool, 10)
  123.                 go func() {
  124.                         for {
  125.                                 select {
  126.                                 case info := <-taskChan:
  127.                                         go func() {
  128.                                                 defer wg.Done()
  129.                                                 var x, y int
  130.                                                 im,err:= gg.LoadImage(info.Path)
  131.                                                 if err != nil {
  132.                                                         log.Printf("LoadImage(%s) error: %v", info.Path, err)
  133.                                                 }
  134.                                                 if im.Bounds().Size().X < im.Bounds().Size().Y {
  135.                                                         im = ScaleImage(im, NY, NX)
  136.                                                         x, y = info.X*(NX+NXInterval)+(NX-NY)/2, info.Y*(NY+NYInterval)
  137.                                                 } else {
  138.                                                         im = ScaleImage(im, NX, NY)
  139.                                                         x, y = info.X*(NX+NXInterval), info.Y*(NY+NYInterval)+(NX-NY)/2
  140.                                                 }
  141.                                                 imgChan <- imgDraw{
  142.                                                         Im:         im,
  143.                                                         X:          x,
  144.                                                         Y:          y,
  145.                                                         StringX:    float64(info.X * (NX + NXInterval)),
  146.                                                         StringY:    float64(info.Y*(NY+NYInterval) + NY + 58),
  147.                                                         StringText: info.Name,
  148.                                                 }
  149.                                                 <-taskSuccessChan
  150.                                         }()
  151.                                 case imgDrawInfo := <-imgChan:
  152.                                         dc.DrawImage(imgDrawInfo.Im, imgDrawInfo.X, imgDrawInfo.Y)
  153.                                         str := getString(imgDrawInfo.StringText, strMaxWidth*2-1)
  154.                                         dc.DrawStringWrapped(str, imgDrawInfo.StringX, imgDrawInfo.StringY, 0, 0, NX, 0, gg.AlignCenter)
  155.                                         wg.Done()
  156.                                 }
  157.                         }
  158.                 }()
  159.                 for y := 0; y < columnNum; y++ {
  160.                         if imgI >= imgNum {
  161.                                 break
  162.                         }
  163.                         for x := 0; x < lineNum; x++ {
  164.                                 if imgI >= imgNum {
  165.                                         break
  166.                                 }
  167.                                 taskChan <- taskInfo{
  168.                                         Path: imgList[imgI].Path + "/" + imgList[imgI].Name,
  169.                                         Name: imgList[imgI].Name,
  170.                                         X:    x,
  171.                                         Y:    y,
  172.                                 }
  173.                                 taskSuccessChan <- true
  174.                                 wg.Add(2)
  175.                                 imgI++
  176.                         }
  177.                 }
  178.                 wg.Wait()
  179.                 im := dc.Image()
  180.                 f, err := os.Create(dir + "/composite.jpeg")
  181.                 if err != nil {
  182.                         panic(err)
  183.                 }
  184.                 jpeg.Encode(f, im, nil)
  185.                 fileName := strings.Replace(dir,".\操作区", "", -1)
  186.                 defer func() {
  187.                         fmt.Println("缩略图生成耗时: ",time.Now().Sub(loadStart).Seconds(),"ms  ",fileName)
  188.                 }()
  189.         }
  190. }
  191. func getString(str string, maxLen int) string {
  192.         text := ""
  193.         w := 0
  194.         strSize := 0
  195.         for _, c := range []rune(str) {
  196.                 if pkg.IsHalfwidth(c) {
  197.                         strSize = 1
  198.                 } else {
  199.                         strSize = 2
  200.                 }
  201.                 w += strSize
  202.                 if w >= maxLen {
  203.                         text += "…"
  204.                         break
  205.                 }
  206.                 text += string(c)
  207.         }
  208.         return text
  209. }
  210. // ScaleImage 缩放图片
  211. func ScaleImage(image image.Image, x, y int) image.Image {
  212.         //loadStart := time.Now()
  213. /*         defer func() {
  214.                 fmt.Printf("缩放耗时: %vn", time.Now().Sub(loadStart).Seconds())
  215.         }() */
  216.         w := image.Bounds().Size().X
  217.         h := image.Bounds().Size().Y
  218.         dc := gg.NewContext(x, y)
  219.         var ax = float64(x) / float64(w)
  220.         var ay = float64(y) / float64(h)
  221.         dc.Scale(ax, ay)
  222.         dc.DrawImage(image, 0, 0)
  223.         return dc.Image()
  224. }
  225. func getImgList(p string) (imgInfoListArr []ImgInfoList) {
  226.         files, _ := ioutil.ReadDir(p)
  227.         var imgInfoList ImgInfoList
  228.         imgInfoList.Path = p
  229.         for _, file := range files {
  230.                 if !file.IsDir() {
  231.                         fileName := file.Name()
  232.                         fileSuffix := strings.ToLower(path.Ext(fileName))
  233.                         if pkg.StringsContains(config.ImgFormat, fileSuffix) {
  234.                                 imgInfoList.ImgInfo = append(imgInfoList.ImgInfo, ImgInfo{
  235.                                         Path:   p,
  236.                                         Size:   file.Size(),
  237.                                         Name:   fileName,
  238.                                         Suffix: fileSuffix,
  239.                                 })
  240.                         }
  241.                 } else {
  242.                         imgInfoListArr = append(imgInfoListArr, getImgList(p+"/"+file.Name())…)
  243.                 }
  244.         }
  245.         if len(imgInfoList.ImgInfo) > 10 {
  246.                 imgInfoListArr = append(imgInfoListArr, imgInfoList)
  247.         }
  248.         return imgInfoListArr
  249. }

复制代码

madegehaol1 发表于 2022-4-12 22:43
im, _ := gg.LoadImage(info.Path)
                                                if im.Bounds().Size …

谢谢老哥,我插入了这个还是会出错                                                if err != nil {
                                                        log.Printf("LoadImage(%s) error: %v", info.Path, err)
                                                }

sdqu 发表于 2022-4-12 22:45
这里99%以上的人看不懂这个,看得懂的1%,也不愿意去帮人免费debug这东西。

唉 实在没办法了只能求助下论坛  从早上改到现在 人都傻了