关键词
- c#
- go
- 本地web
设计思路
用go语言编写本地后台
-
作用:
数据持久化。将数据存入sqlite数据库,还有数据的增删改查,
本地web后端。监听本地1210端口,访问本地1210端口可完成对数据的一系列操作
用c#语言编写程序界面
-
作用:
管理后台服务。启动后台,关闭后台。
与后台交互。通过访问本地端口,实现对数据的一系列操作
代码
后台代码实现
web.go
package main
import (
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
// "strconv"
// "time"
_ "github.com/mattn/go-sqlite3"
)
const (
TIMELIMIT = 10
)
type setting struct {
TIMELIMIT int
}
func main() {
var st setting
log.Println("start read setting")
st.readSetting()
log.Println("read setting is finish")
log.Printf("main: starting HTTP server")
httpServer()
// var srv *http.Server
// srv = new(http.Server)
// srv = httpServer()
// log.Printf("main: serving for " + strconv.Itoa(st.TIMELIMIT) + " seconds")
// time.Sleep(time.Duration(st.TIMELIMIT) * time.Second)
// log.Printf("main: stopping HTTP server")
// now close the server gracefully ("shutdown")
// timeout could be given instead of nil as a https://golang.org/pkg/context/
// if err := srv.Shutdown(nil); err != nil {
// panic(err) // failure/timeout shutting down the server gracefully
// }
// log.Printf("main: done. exiting")
}
func httpServer() {
htmlPath := "./index.html"
srv := &http.Server{Addr: ":1210"}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:1210")
var data []byte
var err error
reqURI := r.RequestURI
switch reqURI {
case "/":
data, err = readFile(htmlPath)
case "/data":
data, err = readSql()
default:
data, err = readFile("." + reqURI)
}
if err == nil {
w.Write(data)
}
})
if err := srv.ListenAndServe(); err != nil {
// cannot panic, because this probably is an intentional close
log.Printf("Httpserver: ListenAndServe() error: %s", err)
}
// go func() {
// if err := srv.ListenAndServe(); err != nil {
// // cannot panic, because this probably is an intentional close
// log.Printf("Httpserver: ListenAndServe() error: %s", err)
// }
// }()
// // returning reference so caller can call Shutdown()
// return srv
}
func (st *setting) readSetting() {
b, err := read("./setting.json")
checkErr(err)
if err := json.Unmarshal(b, st); err != nil {
panic(b)
}
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
type user struct {
id string `json:"id"`
place string `json:"place"`
account string `json:"account"`
password string `json:"password"`
note sql.NullString `json:"note"`
}
func (u *user) out() {
fmt.Println(u.id)
fmt.Println(u.place)
fmt.Println(u.account)
fmt.Println(u.password)
fmt.Println(u.note)
}
func readSql() ([]byte, error) {
return getJSON("select * from sercet")
}
func readFile(filepath string) ([]byte, error) {
return read(filepath)
}
func read(filepath string) ([]byte, error) {
f, err := os.Open(filepath)
if err != nil {
return nil, err
}
return ioutil.ReadAll(f)
}
func getJSON(sqlString string) ([]byte, error) {
db, err := sql.Open("sqlite3", "./sercet.db")
if err != nil {
return nil, err
}
stmt, err := db.Prepare(sqlString)
if err != nil {
return nil, err
}
defer stmt.Close() // defer的作用,在打开stmt后,不管后面的代码流程如何影响,它能够被自动关闭。
rows, err := stmt.Query()
if err != nil {
return nil, err
}
defer rows.Close() // 同上
columns, err := rows.Columns() // 返回[]string, error
if err != nil {
return []byte(""), err
}
count := len(columns)
tableData := make([]map[string]interface{}, 0)
values := make([]interface{}, count)
valuePtrs := make([]interface{}, count)
for rows.Next() {
for i := 0; i < count; i++ {
valuePtrs[i] = &values[i] // 将引用放入数组中
}
rows.Scan(valuePtrs...) // 使用数组获取结果,"..."是
entry := make(map[string]interface{})
for i, col := range columns { // i是数字,col是数组中对应下标i的值
var v interface{}
val := values[i]
b, ok := val.([]byte) // 类型断言(type assertion),简单来说就是看val的类型是不是[]byte
if ok {
v = string(b)
} else {
v = val
}
entry[col] = v
}
tableData = append(tableData, entry)
}
return json.Marshal(tableData)
}
界面代码实现
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PasswordManager
{
public partial class Form1 : Form
{
private Process p;
private progressForm pf;
public Form1()
{
InitializeComponent();
pf = new progressForm();
startWeb();
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
}
private void startWeb()
{
p = new Process();
p.StartInfo.FileName = Application.StartupPath + @"\web2\web.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true; // 标准输入流
p.StartInfo.RedirectStandardOutput = true; // 标准输出流
p.StartInfo.RedirectStandardError = true; // 标准错误流
p.StartInfo.CreateNoWindow = true; // 创建没有窗口
// 工作目录 = 应用启动路径
p.StartInfo.WorkingDirectory = Application.StartupPath + @"\web2\";
p.Start();
webBrowser1.Url = new Uri("http://localhost:1210/");
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
pf.Show();
pf.setValue(0);
Process[] processList = Process.GetProcesses();
foreach (Process p in processList)
{
if (p.ProcessName.ToLower() == "web")
{
pf.setValue(50);
p.Kill();
break;
}
}
pf.setValue(100);
pf.Close();
}
private void setValue(int n)
{
}
/// <summary>
/// 运行DOS命令
/// DOS关闭进程命令(ntsd -c q -p PID )PID为进程的ID
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
private string RunCmd(string command)
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + command;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
return p.StandardOutput.ReadToEnd();
}
}
}