iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
1

寫在前面

有時候程式並沒有得到你的預期效果,直接崩潰或是給出了錯誤的資料
這時候我們就需要Debug
以往我們在看程式執行到底哪一段出錯時都會需要在各種地方印東西

func h2t(number string) (output float64){
	inarr := strings.Split(number, "")
	fmt.Println(inarr) //查看字串被切割後的模樣
	i:=0
	for i < len(inarr) {
		fmt.Println(len(inarr)-(i+1)) //查看算出的東西
        output += AEreturn(inarr[i]) * math.Pow(16, float64(len(inarr)-(i+1)))
        fmt.Println(output) //查看目前的output是否符合預期的結果
		i++
	}
	return
}

當程式還沒有很複雜時當然可以使用這種方式來查詢BUG,
但當你的程式會有各種進入點及回傳點後這種方式反而會讓你認不出現在程式到底執行到哪

因此我們有了單行執行
以下我們使用golang作為示範,各種語言都有各自的方式可以實作

如何開始

先進到當初我們學golang時建立的資料夾吧
點選左側的檔案開啟你的主執行檔後,之後分別依序點擊VScode的按鈕

https://ithelp.ithome.com.tw/upload/images/20200928/20127836TdoZGlgW4h.png

然後你應該會看到上方冒出選擇

https://ithelp.ithome.com.tw/upload/images/20200928/20127836O6VP4TpYqN.png

直接點選他之後應該就可以看到你的debug設定擋了

https://ithelp.ithome.com.tw/upload/images/20200928/20127836AQQCKvURof.png

如果沒辦法產生設定檔去VScode的右下角看看是不是工具沒有安裝

https://ithelp.ithome.com.tw/upload/images/20200928/20127836dkRWuV86Yo.png

安裝之後應該就沒問題了

設定檔裡面有許多可以玩的東西,不過我們這邊先不做詳細介紹
有興趣可以前往這裡查看

開始Debug

之後在你的程式碼內行號的左側加上一個中斷點(別懷疑,就是那個空無一物的地方)

https://ithelp.ithome.com.tw/upload/images/20200928/20127836yhRFZZjTtU.png

之後按下F5

https://ithelp.ithome.com.tw/upload/images/20200928/20127836HmjWnanLom.png

程式碼就會開始執行並且停在你下中斷點的地方
此時按下F10將會讓你單行執行

https://ithelp.ithome.com.tw/upload/images/20200928/20127836dzDTRMqrZj.png

按下F11會讓你進入到下一層
(也就是如果有執行方法的話會讓你進入那個方法)

https://ithelp.ithome.com.tw/upload/images/20200928/20127836neTo7jcNfP.png

此時如果再次按下F5時將會讓程式繼續執行到下一個中斷點
當然,如果沒有的話就會直接執行到程式結束

這時你應該會發現原本你的程式是有讀取輸入的部份
但是被debug模式跳過了
要在debug模式下可以讀取輸入的方法有很多種,但是各個語言都不一樣
因此我們用土法煉鋼的方式來吧

在你的程式碼內加上

input = "1"

來模擬輸入,並且增加一個中斷點

https://ithelp.ithome.com.tw/upload/images/20200928/20127836BdX5L8umWH.png

這時候再度進入debug模式後應該就可以看到你的程式順利進入到switch內了

https://ithelp.ithome.com.tw/upload/images/20200928/20127836FeZS98hKin.png

之後繼續修改你的程式,以便讓他可以進入到t2h這個方法
你可以在

fmt.Println(t2h(number))

這行下中斷,之後使用F11進入到方法內

型別與變數

case "1":
	var number string
	fmt.Println("Please enter the number:")
	fmt.Scanln(&number)
	number = "3524"
	fmt.Println(t2h(number))

如果你跟我一樣在丟入變數時選擇給他"3524"這個字串

那麼你就會看到這樣

https://ithelp.ithome.com.tw/upload/images/20200928/20127836hlzjTc1VlK.png

當然,你可以逐步按F10看 i j k 這三個變數的變化
不過我們這邊直接看到最終的結果
此時你可以看到左邊的變數欄
輸入的變數
number為字串"3524",轉型後為tenum 3524

這樣你就可以不必到處去印各種log來確認程式執行到哪以及變數的值目前是什麼了

breakpoint

之後看到左下角

https://ithelp.ithome.com.tw/upload/images/20200928/20127836jRuR0DYXXC.png

有看到這三個按鈕嗎?
沒看到也沒關係,把滑鼠移過去就看得到了
你可以嘗試點擊這三個按紐看看會發生什麼事

中間的會幫你暫時取消中斷點,好讓你可以在正常執行與debug中切換
最右邊的則會直接幫你取消所有的中斷點

其他操作

我們來看看左上角的這些按鈕吧

https://ithelp.ithome.com.tw/upload/images/20200928/20127836LozIWXybrt.png

你可以將滑鼠移到符號上面,看看這些按鈕的快捷鍵是哪些

shift+F11跟F11剛好相反,是跳出進入的方法(通常用於你不小心跳入了底層的方法時)
紅色的按鈕為直接中斷debug
綠色則是重新開始debug(同時會重新編譯你的程式碼)

執行參數

我們來看看怎麼樣在debug時帶入參數吧
golang有提供執行參數的作法flag,我們就使用這個來做示範

package main

import (
	"flag"
	"fmt"
)

var (
	flaginput int
)

func main() {
	flag.IntVar(&flaginput, "intflag", 0, "int flag value")
	flag.Parse()
	fmt.Println("int flag:", flaginput)
}

launch.json設定檔

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${workspaceFolder}/main.go",
            "env": {},
            "args": ["-intflag=15"]
        }
    ]
}

在args裡面添加要帶入的參數"-intflag=15"
program裡面的設定"${workspaceFolder}/main.go"只是我的習慣,你們可以不必更動他

設定完之後debug時就會帶入參數

go run main.go -intflag=15

此時由於我們有設定執行參數

flag.IntVar(&flaginput, "intflag", 0, "int flag value")

執行後就會為你的flaginput這個參數帶入15這個值

按下F5看看是不是真的會帶入15吧

執行參數通常是拿來做什麼用的?

通常是拿來帶入一些你執行時才會主動帶入的值
比方說

for i :=0; i< flaginput ; i++{
	fmt.Println(i)
}

或是上面我們要帶入進位轉換程式的值時也可以用這個方法

那為什麼不先介紹帶入的方法之後再教debug呢?

理由是因為每種程式語言帶入的方式都不同,而且這篇主要是教debug,執行參數只是順代一提

多個設定檔

每個config都可以有多種設定檔,比方說你可以修改你的設定檔如下

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${workspaceFolder}/main.go",
            "env": {},
            "args": ["-intflag=15"]
        },
        {
            "name": "Launch Test20",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${workspaceFolder}/main.go",
            "env": {},
            "args": ["-intflag=20"]
        }
    ]
}

記得每個設定檔中間都要有,去分隔
之後左上角的執行設定就會有兩種了

https://ithelp.ithome.com.tw/upload/images/20200928/20127836D5Xhq4Syzr.png

分別去選兩種設定檔都會有不同的結果

chrome的單行執行

如果是前端的工程師,必備的工具google chrom也有自己的debug工具,就在F12裡面

https://ithelp.ithome.com.tw/upload/images/20200928/20127836n4apUub2xj.png

記得先下中斷後,執行程式就可以看到程式會在你想要的位置中斷了

小結

Debug算是工程師必備的功課
有些人可能會想只要程式寫得穩,就不需要具備這項技能
但實際上,你有時候會需要看別人的程式碼
不管是同事的或是網路上抄來的,程式語言底層的或是官方的library
使用debug模式進去看每行程式在做什麼都會讓你更了解他


上一篇
附錄2. 參考與指標 Reference, or not reference: that is the question
下一篇
附錄4. 資料結構 想刷leetcode? 學好資料結構跟演算法吧
系列文
你會十五種程式語言?不,我會十五種HelloWorld.為了避免這種狀況,因此寫了這篇:淺入淺出十五種程式語言30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言