這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
我也是剛剛使用walk這個組件,很多控制項介面不熟悉,把我上次發的郵件群發器修改成圖形介面的,線程發送郵件,gob庫儲存資料等。只提供作學習交流,僅供參考(介面很爛)。
接下來是main.go的代碼:
// Multi-SendEmail project main.gopackage mainimport ( "bufio" "encoding/gob" "errors" "fmt" "io" "net/smtp" "os" "strconv" "strings" "time")import ( "github.com/lxn/walk" . "github.com/lxn/walk/declarative")type ShuJu struct { Name string Pwd string Host string Subject string Body string Send string}func SendMail(user, password, host, to, subject, body, mailtype string) error { fmt.Println("Send to " + to) //fmt.Println(user, password, host, to, subject, body, mailtype) hp := strings.Split(host, ":") auth := smtp.PlainAuth("", user, password, hp[0]) var content_type string if mailtype == "html" { content_type = "Content-Type: text/html;charset=UTF-8" } else { content_type = "Content-Type: text/plain;charset=UTF-8" } body = strings.TrimSpace(body) msg := []byte("To: " + to + "\r\nFrom: " + user + "<" + user + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body) send_to := strings.Split(to, ";") err := smtp.SendMail(host, auth, user, send_to, msg) if err != nil { fmt.Println(err.Error()) } return err}func readLine2Array(filename string) ([]string, error) { result := make([]string, 0) file, err := os.Open(filename) if err != nil { return result, errors.New("Open file failed.") } defer file.Close() bf := bufio.NewReader(file) for { line, isPrefix, err1 := bf.ReadLine() if err1 != nil { if err1 != io.EOF { return result, errors.New("ReadLine no finish") } break } if isPrefix { return result, errors.New("Line is too long") } str := string(line) result = append(result, str) } return result, nil}func DelArrayVar(arr []string, str string) []string { str = strings.TrimSpace(str) for i, v := range arr { v = strings.TrimSpace(v) if v == str { if i == len(arr) { return arr[0 : i-1] } if i == 0 { return arr[1:len(arr)] } a1 := arr[0:i] a2 := arr[i+1 : len(arr)] return append(a1, a2...) } } return arr}func LoadData() { fmt.Println("LoadData") file, err := os.Open("data.dat") defer file.Close() if err != nil { fmt.Println(err.Error()) SJ.Name = "使用者名稱" SJ.Pwd = "使用者密碼" SJ.Host = "SMTP伺服器:連接埠" SJ.Subject = "郵件主題" SJ.Body = "郵件內容" SJ.Send = "要發送的郵箱,每行一個" return } dec := gob.NewDecoder(file) err2 := dec.Decode(&SJ) if err2 != nil { fmt.Println(err2.Error()) SJ.Name = "使用者名稱" SJ.Pwd = "使用者密碼" SJ.Host = "SMTP伺服器:連接埠" SJ.Subject = "郵件主題" SJ.Body = "郵件內容" SJ.Send = "要發送的郵箱,每行一個" }}func SaveData() { fmt.Println("SaveData") file, err := os.Create("data.dat") defer file.Close() if err != nil { fmt.Println(err) } enc := gob.NewEncoder(file) err2 := enc.Encode(SJ) if err2 != nil { fmt.Println(err2) }}var SJ ShuJuvar runing boolvar chEnd chan boolfunc main() { LoadData() chEnd = make(chan bool) var emails, body, msgbox *walk.TextEdit var user, password, host, subject *walk.LineEdit var startBtn *walk.PushButton MainWindow{ Title: "郵件群發器 By 一曲憂傷", MinSize: Size{800, 600}, Layout: HBox{}, Children: []Widget{ TextEdit{AssignTo: &emails, Text: SJ.Send, ToolTipText: "待發送郵件清單,每行一個"}, VSplitter{ Children: []Widget{ LineEdit{AssignTo: &user, Text: SJ.Name, CueBanner: "請輸入信箱使用者名"}, LineEdit{AssignTo: &password, Text: SJ.Pwd, PasswordMode: true, CueBanner: "請輸入郵箱登入密碼"}, LineEdit{AssignTo: &host, Text: SJ.Host, CueBanner: "SMTP伺服器:連接埠"}, LineEdit{AssignTo: &subject, Text: SJ.Subject, CueBanner: "請輸入郵件主題……"}, TextEdit{AssignTo: &body, Text: SJ.Body, ToolTipText: "請輸入郵件內容", ColumnSpan: 2}, TextEdit{AssignTo: &msgbox, ReadOnly: true}, PushButton{ AssignTo: &startBtn, Text: "開始群發", OnClicked: func() { SJ.Name = user.Text() SJ.Pwd = password.Text() SJ.Host = host.Text() SJ.Subject = subject.Text() SJ.Body = body.Text() SJ.Send = emails.Text() SaveData() if runing == false { runing = true startBtn.SetText("停止發送") go sendThread(msgbox, emails) } else { runing = false startBtn.SetText("開始群發") } }, }, }, }, }, }.Run()}func sendThread(msgbox, es *walk.TextEdit) { sendTo := strings.Split(SJ.Send, "\r\n") susscess := 0 count := len(sendTo) for index, to := range sendTo { if runing == false { break } msgbox.SetText("發送到" + to + "..." + strconv.Itoa((index/count)*100) + "%") err := SendMail(SJ.Name, SJ.Pwd, SJ.Host, to, SJ.Subject, SJ.Body, "html") if err != nil { msgbox.AppendText("\r\n失敗:" + err.Error() + "\r\n") if err.Error() == "550 Mailbox not found or access denied" { SJ.Send = strings.Join(DelArrayVar(strings.Split(SJ.Send, "\r\n"), to), "\r\n") es.SetText(SJ.Send) } time.Sleep(1 * time.Second) continue } else { susscess++ msgbox.AppendText("\r\n發送成功!") SJ.Send = strings.Join(DelArrayVar(strings.Split(SJ.Send, "\r\n"), to), "\r\n") es.SetText(SJ.Send) } time.Sleep(1 * time.Second) } SaveData() msgbox.AppendText("停止發送!成功 " + strconv.Itoa(susscess) + " 條\r\n")}
然後是walk程式所用的main.manifest,完全照抄官方的,還沒研究其中意思:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> </dependentAssembly> </dependency></assembly>
通過這個main.manifest執行(如果walk安裝好了,應該就有這個命令):
rsrc -manifest main.manifest -o rsrc.syso
是rsrc命令的參數列表,比如我為自已的程式加個ico表徵圖:
rsrc -manifest main.manifest –ico icon.ico -o rsrc.syso
總結:只要熟悉這些非常強大的第三方庫,Go應該也可以做出非常不錯的圖形應用程式,對於接觸C、C++過晚的朋友來說非常合適。
=====================國際慣例=======================
剛開始學著寫一些部落格,寫得不好的地方請見諒,覺得學到了的就賞臉關注下吧~
我的QQ群(PHP)336533596,QQ 451309839,歡迎加入。相互交流,聊天吹牛~