二十四、WEB开发

1.HTML

常用标签
注释
标题 h1~h6
段落 p
超链接 a
图片 img
表单 form
input: text/password/radio/checkbox/file/date/datetime/url/submit/hidden
textarea
select/option
按钮 button
表格 table/thead/tbody/tr/td/th
列表 ol/ul/li
块 div/span
…….

<!DOCTYPE html>
>
>
    -8">
    >我的第一个页面>
>
>
    我叫aa
    ://www.baidu.com" target="_blank">百度>
    ://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1585021686&di=90e0a79359a4f6aa14cc1dc1c7a81200&src=http://gss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/b999a9014c086e06b273602204087bf40bd1cb84.jpg">
    >
        >
        >
            >姓名>
            >联系方式>
        >
        >
        >
        >
            >aa>
            >133888>
        >
        >
    >
>
>

2.WEB开发

(1)应用开发
http包提供了HTTP服务器和客户端的开发接口,内置web服务器
针对web服务端开发流程为
定义处理器/处理器函数
接收用户数据
返回信息
启动web服务器

(2)常用函数
ListenAndServer:使用http协议启动web服务
Handle:定义url对应处理器
HandleFunc:定义url对应处理器函数
Redirect:重定向
SetCookie:设置Cookie
FileServer: 创建静态文件处理器
(3)常用结构体
①Request
常用属性
Method: 请求方式
URL:请求的URL
Proto:请求协议
Header:请求头
ContentLength:请求体字节数量
Body:请求体流对象
Form:获取提交的所有数据,需要手动调用ParseForm
PostForm:获取所有body中提交的数据(application/x-www-form-urlencoded) ,需要手动调用ParseForm
MultipartForm:获取所有body中提交的数据(multipart/form-data) ,需要手动调用ParseMutipartForm
常用方法
ParseForm:解析提交的数据(url&body[application/x-www-form-urlencode])
FormValue:根据名称获取提交的数据,自动调用ParseForm
PostFormValue:根据名称从body中获取提交的数据,自动调用ParseForm
ParseMultipartForm:解析提交的数据(url*body[multipart/form-data])
FormFile:根据名称从body中获取提交的文件数据流对象,自动调用ParseMutipartForm,ParseForm

②Reponse
常用属性
Status:响应状态
StatusCode:响应状态码
Proto:协议信息
Header:响应头
ContentLength:响应体字节数量
Body:响应体流对象
常用方法
Cookies:cookie信息
Location:location信息
Write:将响应体写入输出流
常用接口
ResponseWriter
常用方法:
Write:写入响应体
Header:写入响应头信息
WriteHeader:写入请求行状态码(在调用后不能Write和设置Header信息)
常用结构体
Header
常用方法
Set:设置头信息
Add:添加头信息
Del:删除头信息
Get:获取头信息

3.UDP

//server
package main

import (
   "fmt"
   "net"
   "os"
)

func main() {
   addr := "0.0.0.0:9999"
   server,err := net.ListenPacket("udp",addr)

   if err != nil {
      fmt.Println(err)
      os.Exit(-1)
   }
   for {
      bytes := make([]byte,1024)
      n,addr,err := server.ReadFrom(bytes)
      fmt.Println(n,addr,err,string(bytes))
      //写消息给谁
      server.WriteTo([]byte("hi"),addr)
   }
}
//client
package main

import (
   "fmt"
   "net"
   "os"
   "time"
)

func main() {
   addr := "192.168.0.105:9999"
   conn,err := net.Dial("udp",addr)
   if err != nil {
      fmt.Println(err)
      os.Exit(-1)
   }
   defer  conn.Close()
   fmt.Fprintf(conn,"Time %s:",time.Now().Format("2016-01-02 "))

   bytes := make([]byte,1024)
   n,err := conn.Read(bytes)
   fmt.Println(n,err,string(bytes[:n]))
}

4.net包

package main

import (
   "fmt"
   "net"
)

func main() {
   //拼接ip+端口
   fmt.Println(net.JoinHostPort("0.0.0.0","8888"))

   //吧ip:端口 拆分为 ip  端口
   fmt.Println(net.SplitHostPort("192.168.1.1:8888"))

   //根据ip查找对应主机
   fmt.Println(net.LookupAddr("39.156.69.79" ))

   //根据域名查找对应主机ip
   fmt.Println(net.LookupHost("www.baidu.com"))
   //带掩码格式 打印你的ip 以及你的网络子网范围
   fmt.Println(net.ParseCIDR("192.168.1.1/24"))
   //可以解析ipv4  跟ipv6  返回一个IP类型的    ip的类型是[]byte
   ip01 := net.ParseIP("::1")
   ip02 := net.ParseIP("192.168.1.100")
   //解析失败会返回一个nil
   fmt.Println(ip01)
   fmt.Println(ip02)
   //返LookupIP返回的是一个ip的集合  也就是切片 和err
   ip03 ,err:= net.LookupIP("www.baidu.com")
   fmt.Println(ip03,err)

   ip,ipnet,err := net.ParseCIDR("192.168.1.1/24")
   //判断ip是否在 cidr范围内
   fmt.Println(ipnet.Contains(net.ParseIP("192.168.1.40")))
   fmt.Println(ipnet.Contains(net.ParseIP("193.168.1.40")))
   fmt.Println(ipnet.Network())
   fmt.Println(ip)

   addrs ,_ := net.InterfaceAddrs()
   for _,addr := range addrs {
      fmt.Println(addr.String(),addr.Network())
   }

   inters,_ := net.Interfaces()
   for _,inter := range inters{
      fmt.Println(inter.Name,inter.Index,inter.Flags,inter.MTU,inter.HardwareAddr)
      fmt.Println(inter.Addrs())
      fmt.Println(inter.MulticastAddrs())
   }
}

5.http

//server
package main

import (
   "fmt"
   "io"
   "net/http"
   "os"
   "time"
)

func Time(w http.ResponseWriter,r *http.Request) {
   fmt.Fprintf(w,"Time:%d",time.Now().Unix())
}

type Test03 struct {}
//处理器
func (a Test03) ServeHTTP(w http.ResponseWriter,r *http.Request){
   fmt.Fprintf(w,"Time: %s",time.Now().Format("2006-1-2 15:02:01"))
}

func main() {
   //定义处理器函数
   http.HandleFunc("/test", func(w http.ResponseWriter,r *http.Request) {
      w.Write([]byte("hello"))
   })

   http.HandleFunc("/test02",Time)

   http.Handle("/test03",Test03{})


   http.HandleFunc("/test04", func(w http.ResponseWriter,r *http.Request) {
      //请求行
      fmt.Println(r.UserAgent())
      fmt.Println(r.Referer())
      fmt.Println(r.Method,r.URL,r.Proto)
      //请求头
      fmt.Println(r.Header)
      //请求体
      //bytes := make([]byte,1024)
      //n,_ := r.Body.Read(bytes)
      //fmt.Println(string(bytes[:n]))
      //把r.body copy至标准输入   里面也是有循环判断是否io.eof
      io.Copy(os.Stdin,r.Body)
      w.Write([]byte("Request"))
   })
   //启动一个文件服务器
   //表示当前目录所有
   http.Handle("/",http.FileServer(http.Dir(".")))
   //在当前目录下的file文件夹中
   //http.Handle("/file",http.FileServer(http.Dir(".")))

   err := http.ListenAndServe("0.0.0.0:9999",nil)
   if err != nil {
      fmt.Println(err)
   }
}
//client-v1
package main

import (
   "bytes"
   "fmt"
   "io"
   "net/http"
   "net/url"
   "os"
)

func main() {
   url01 := "http://127.0.0.1:9999/test04"
   //get用于获取   //post用于修改
   response ,err := http.Get(url01)
   if err == nil {
      //协议以及状态信息
      fmt.Println(response.Proto,response.Status)
      //头部信息
      fmt.Println(response.Header)
      //请求体
      io.Copy(os.Stdout,response.Body)
      fmt.Println()
   }

   json := bytes.NewReader([]byte(`{"name" : "kk","password" : "12345}`))
   response,err = http.Post(url01,"application/json",json)
   if err == nil {
      //协议以及状态信息
      fmt.Println(response.Proto,response.Status)
      //头部信息
      fmt.Println(response.Header)
      //请求体
      io.Copy(os.Stdout,response.Body)
      fmt.Println()
   }

   params := make(url.Values)
   params.Add("name","k")
   params.Add("password","123")

   response,err = http.PostForm(url01,params)
   if err == nil {
      //协议以及状态信息
      fmt.Println(response.Proto,response.Status)
      //头部信息
      fmt.Println(response.Header)
      //请求体
      io.Copy(os.Stdout,response.Body)
      fmt.Println()
   }
}
//client-v2
package main

import (
   "crypto/tls"
   "fmt"
   "io"
   "net/http"
   "os"
)

func main() {
   url := "http://localhost:9999/test04"
   //delete 表示删除
   request,_ := http.NewRequest("DELETE",url,nil)
   //这个配置true可以跳过认证 比如某些自作证书的https网站 不信任的 可以跳过
   transport := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify:true}}
   client := &http.Client{Transport:transport}
   response,err := client.Do(request)

   if err == nil {
      //协议以及状态信息
      fmt.Println(response.Proto,response.Status)
      //头部信息
      fmt.Println(response.Header)
      //请求体
      io.Copy(os.Stdout,response.Body)
      fmt.Println()
   }
}

6.爬虫

package main

import (
   "bytes"
   "fmt"
   "github.com/PuerkitoBio/goquery"
   "io/ioutil"
   "strings"
)

func main() {
   //url := "https://www.zhipin.com/c101010100/y_6-s_304/?query=devops&ka=sel-scale-304"
   //request,_ := http.NewRequest("GET",url,nil)
   //boss需要日换cokey
   //request.Header.Set("cookie","lastCity=101010100; t=th0PstY21h4TF20h; wt=th0PstY21h4TF20h; __c=1585034869; __g=-; __l=l=%2Fwww.zhipin.com%2Fweb%2Fgeek%2Frecommend&r=https%3A%2F%2Fcn.bing.com%2F&friend_source=0&friend_source=0; Hm_lvt_194df3105ad7148dcf2b98a91b5e727a=1584923226,1584946519,1585017679,1585034876; Hm_lpvt_194df3105ad7148dcf2b98a91b5e727a=1585047125; __zp_stoken__=dd77Ir6UHeMCkG9IDXlYw0Is19q0%2FX2QYixRWRtlZY0JEQiqcjN4cDzoSatQk98YCfA%2Fnd%2BgY0uctWDLVmAa9TKIyP0zN2OIOOJq6yUL2ADAigua4G89LJ7fToCDutRAlwPV; __zp_sseed__=JACbDVsIkXRju/l3PNgAstDGEk8JM+S+l5MjXRhUBcc=; __zp_sname__=ea550e23; __zp_sts__=1585047371082; __a=48396892.1584923226.1585009959.1585034869.73.10.25.73")
   //client := &http.Client{}
   //response,_ := client.Do(request)
   //document ,_:= goquery.NewDocumentFromResponse(response)
   //readfile 返回值是一个[]byte
   cxt,_ := ioutil.ReadFile("job.html")
   //因为NewDocumentFromReader 参数是一个reader 所以需要给[]byte 封装一个reader
   reader := bytes.NewReader(cxt)
   document,_ := goquery.NewDocumentFromReader(reader)
   //fmt.Println(err,document)
   //fmt.Println(document.Html())
   document.Find("div.job-primary").Each(func(i int, selection *goquery.Selection) {
      fmt.Println(strings.Repeat("-",20))
      //fmt.Println(selection.Html())
      fmt.Println(selection.Find("div.info-company > div.company-text > h3 > a").Text())
      tagA := selection.Find("div.info-primary> div.primary-wrapper >a ")
      fmt.Println(tagA.Find("div.job-title > span.job-name").Text())
      fmt.Println(tagA.Find("div.job-limit > span.red").Text())
   })

}

7.RPC

二十四、WEB开发_第1张图片

//client
package main

import (
   "fmt"
   "net/rpc/jsonrpc"
   "test/object"
)

func main() {
   //获取连接
   client,err := jsonrpc.Dial("tcp","127.0.0.1:9999")
   if err == nil {
      //定义请求对象/响应对象
      request := object.Request{5,10}
      var response object.Response
      //调用远程方法
      err := client.Call("Calc.Sum",&request,&response)
      if err == nil {
         fmt.Println(response.Result)
      }else {
         fmt.Println(err)
      }
   }else {
      fmt.Println(err)
   }
}
//main
package main

import (
   "fmt"
   "net"
   "net/rpc"
   "net/rpc/jsonrpc"
   "test/object"
)

func main() {
   //注册RPC服务
   rpc.Register(&object.Calc{})
   server ,err := net.Listen("tcp",":9999")
   if err != nil {
      fmt.Println(err)
   }
   defer  server.Close()
   for {
      client,err := server.Accept()
      if err == nil {
         jsonrpc.ServeConn(client) //使用jsonrpc处理客户端连接
      }
   }

}
//rpc
package object

import "fmt"

type Request struct {
   Left int
   Right int
}

type Response struct {
   Result int
}

type Calc struct {}

func (c *Calc) Sum(r *Request , rp *Response) error{
   fmt.Println("Sum",r.Left,r.Right)
   rp.Result =  r.Left + r.Right
   return  nil
}

你可能感兴趣的:(GO语言编程)