我也是刚刚使用walk这个组件,很多控件接口不熟悉,把我上次发的邮件群发器修改成图形界面的,线程发送邮件,gob库保存数据等。只提供作学习交流,仅供参考(界面很烂)。
接下来是main.go的代码:
//Multi-SendEmailprojectmain.go packagemain import( "bufio" "encoding/gob" "errors" "fmt" "io" "net/smtp" "os" "strconv" "strings" "time" ) import( "github.com/lxn/walk" ."github.com/lxn/walk/declarative" ) typeShuJustruct{ Namestring Pwdstring Hoststring Subjectstring Bodystring Sendstring } funcSendMail(user,password,host,to,subject,body,mailtypestring)error{ fmt.Println("Sendto"+to) //fmt.Println(user,mailtype) hp:=strings.Split(host,":") auth:=smtp.PlainAuth("",user,hp[0]) varcontent_typestring ifmailtype=="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,send_to,msg) iferr!=nil{ fmt.Println(err.Error()) } returnerr } funcreadLine2Array(filenamestring)([]string,error){ result:=make([]string,0) file,err:=os.Open(filename) iferr!=nil{ returnresult,errors.New("OpenfileFailed.") } deferfile.Close() bf:=bufio.NewReader(file) for{ line,isPrefix,err1:=bf.ReadLine() iferr1!=nil{ iferr1!=io.EOF{ returnresult,errors.New("ReadLinenofinish") } break } ifisPrefix{ returnresult,errors.New("Lineistoolong") } str:=string(line) result=append(result,str) } returnresult,nil } funcDelArrayVar(arr[]string,strstring)[]string{ str=strings.TrimSpace(str) fori,v:=rangearr{ v=strings.TrimSpace(v) ifv==str{ ifi==len(arr){ returnarr[0:i-1] } ifi==0{ returnarr[1:len(arr)] } a1:=arr[0:i] a2:=arr[i+1:len(arr)] returnappend(a1,a2...) } } returnarr } funcLoadData(){ fmt.Println("LoadData") file,err:=os.Open("data.dat") deferfile.Close() iferr!=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) iferr2!=nil{ fmt.Println(err2.Error()) SJ.Name="用户名" SJ.Pwd="用户密码" SJ.Host="SMTP服务器:端口" SJ.Subject="邮件主题" SJ.Body="邮件内容" SJ.Send="要发送的邮箱,每行一个" } } funcSaveData(){ fmt.Println("SaveData") file,err:=os.Create("data.dat") deferfile.Close() iferr!=nil{ fmt.Println(err) } enc:=gob.NewEncoder(file) err2:=enc.Encode(SJ) iferr2!=nil{ fmt.Println(err2) } } varSJShuJu varruningbool varchEndchanbool funcmain(){ LoadData() chEnd=make(chanbool) varemails,msgBox*walk.TextEdit varuser,subject*walk.LineEdit varstartBtn*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() ifruning==false{ runing=true startBtn.SetText("停止发送") gosendThread(msgBox,emails) }else{ runing=false startBtn.SetText("开始群发") } },},}.Run() } funcsendThread(msgBox,es*walk.TextEdit){ sendTo:=strings.Split(SJ.Send,"\r\n") susscess:=0 count:=len(sendTo) forindex,to:=rangesendTo{ ifruning==false{ break } msgBox.SetText("发送到"+to+"..."+strconv.Itoa(int((float32(index)/float32(count))*100))+"%") err:=SendMail(SJ.Name,SJ.Pwd,SJ.Host,SJ.Subject,SJ.Body,"html") iferr!=nil{ msgBox.AppendText("\r\n失败:"+err.Error()+"\r\n") iferr.Error()=="550MailBoxnotfoundoraccessdenied"{ 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") es.SetText(SJ.Send) } time.Sleep(1*time.Second) } SaveData() msgBox.SetText("停止发送!共成功"+strconv.Itoa(susscess)+"条\r\n") }
然后是walk程序所用的main.manifest,完全照抄官方的,还没研究其中意思:
<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?> <assemblyxmlns="urn:schemas-microsoft-com:asm.v1"manifestVersion="1.0"> <assemblyIdentityversion="1.0.0.0"processorArchitecture="*"name="SomeFunkyNameHere"type="win32"/> <dependency> <dependentAssembly> <assemblyIdentitytype="win32"name="Microsoft.Windows.Common-Controls"version="6.0.0.0"processorArchitecture="*"publicKeyToken="6595b64144ccf1df"language="*"/> </dependentAssembly> </dependency> </assembly>
通过这个main.manifest执行(如果walk安装好了,应该就有这个命令):
rsrc-manifestmain.manifest-orsrc.syso
上图是rsrc命令的参数列表,比如我为自已的程序加个ico图标:
rsrc-manifestmain.manifest–icoicon.ico-orsrc.syso
附上软件运行截图:
总结:只要熟悉这些非常强大的第三方库,Go应该也可以做出非常不错的图形应用程序,对于接触C、C++过晚的朋友来说非常合适。