day9接口 练习7.1-7.4
parent
619a2a8929
commit
726c9c1a14
|
@ -0,0 +1,44 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 使用来自ByteCounter的思路,实现一个针对单词和行数的计数器。你会发现bufio.ScanWords非常的有用。
|
||||
type WordsCount int
|
||||
type LinesCount int
|
||||
|
||||
func (s *WordsCount) Write(p []byte) (n int, err error) {
|
||||
var sc = bufio.NewScanner(bytes.NewReader(p))
|
||||
sc.Split(bufio.ScanWords)
|
||||
for sc.Scan() {
|
||||
// 由于是值传递, 这里想改变原调用者的值, 必须使用指针
|
||||
*s++
|
||||
}
|
||||
return int(*s), nil
|
||||
}
|
||||
|
||||
func (s *LinesCount) Write(p []byte) (n int, err error) {
|
||||
var sc = bufio.NewScanner(bytes.NewReader(p))
|
||||
sc.Split(bufio.ScanLines)
|
||||
for sc.Scan() {
|
||||
*s++
|
||||
}
|
||||
return int(*s), nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var wc WordsCount
|
||||
wc.Write([]byte("hello world"))
|
||||
var lc LinesCount
|
||||
lc.Write([]byte(`hello
|
||||
1
|
||||
2
|
||||
3
|
||||
world`))
|
||||
fmt.Println(wc, lc)
|
||||
fmt.Fprintf(&wc, "Hello, %s", "dugulp")
|
||||
fmt.Println(wc, lc)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// 封装一个结构体, 此结构体不对外导出
|
||||
// 内部的两个元素同样是不对外导出的, 只能通过CountingWriter方法获取
|
||||
type countWriter struct {
|
||||
w io.Writer
|
||||
c *int64
|
||||
}
|
||||
|
||||
func (c countWriter) Write(p []byte) (n int, err error) {
|
||||
var sc = bufio.NewScanner(bytes.NewReader(p))
|
||||
sc.Split(bufio.ScanWords)
|
||||
for sc.Scan() {
|
||||
// 由于是值传递, 这里想改变原调用者的值, 必须使用指针
|
||||
// 此处n++是要计算新增的单词数
|
||||
n++
|
||||
// 此处c++是总的单词数
|
||||
*c.c++
|
||||
}
|
||||
return int(n), nil
|
||||
}
|
||||
|
||||
func CountingWriter(w io.Writer) (io.Writer, *int64) {
|
||||
var c int64
|
||||
return &countWriter{w, &c}, &c
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type tree struct {
|
||||
value int
|
||||
left, right *tree
|
||||
}
|
||||
|
||||
// 实现Stringer接口
|
||||
func (tree *tree) String() string {
|
||||
var values []int
|
||||
values = appendValues(values, tree)
|
||||
return fmt.Sprint(values)
|
||||
}
|
||||
|
||||
// Build 构建二叉树
|
||||
func Build(nums []int) *tree {
|
||||
var root *tree
|
||||
for _, v := range nums {
|
||||
root = add(root, v)
|
||||
}
|
||||
return root
|
||||
}
|
||||
|
||||
// Sort 排序
|
||||
func Sort(values []int) {
|
||||
var root = Build(values)
|
||||
// 将二叉树还原为切片
|
||||
appendValues(values[:0], root)
|
||||
}
|
||||
func appendValues(values []int, t *tree) []int {
|
||||
if t != nil {
|
||||
values = appendValues(values, t.left)
|
||||
values = append(values, t.value)
|
||||
values = appendValues(values, t.right)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// 建树
|
||||
func add(t *tree, value int) *tree {
|
||||
if t == nil {
|
||||
t = new(tree)
|
||||
t.value = value
|
||||
return t
|
||||
}
|
||||
if value < t.value {
|
||||
t.left = add(t.left, value)
|
||||
//fmt.Println("left", t.value)
|
||||
} else {
|
||||
t.right = add(t.right, value)
|
||||
//fmt.Println("right", t.value)
|
||||
}
|
||||
//fmt.Println(value)
|
||||
return t
|
||||
}
|
||||
func main() {
|
||||
var nums []int = []int{4, 5, 43, 323, 45, 98, 4, 5, 7, 8, 1, 3, 2, 565}
|
||||
var tree = Build(nums)
|
||||
fmt.Println(tree.String())
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/net/html"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Html interface {
|
||||
io.ReadCloser
|
||||
Getdoc(url string) (err error)
|
||||
ForeachNode(n *html.Node, pre, post func(n *html.Node))
|
||||
SearchNode(tag string) []*html.Node
|
||||
PrintAll()
|
||||
}
|
||||
|
||||
// 不对外暴露,一切操作均通过方法实现
|
||||
// 除了Html接口中定义的方法, 还可以自己拓展方法, 例如Show方法
|
||||
type htmlParser struct {
|
||||
Html
|
||||
str string
|
||||
node *html.Node
|
||||
resp *http.Response
|
||||
}
|
||||
|
||||
// 自定义读入
|
||||
func (doc *htmlParser) Read(p []byte) (n int, err error) {
|
||||
if len(p) == 0 {
|
||||
return 0, fmt.Errorf("error, read data is empty")
|
||||
}
|
||||
n = copy(p, doc.str)
|
||||
if doc.node != nil {
|
||||
return 0, fmt.Errorf("error, node is not empty")
|
||||
}
|
||||
doc.node, err = html.Parse(strings.NewReader(doc.str))
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Clear 清空
|
||||
func (doc *htmlParser) Clear() {
|
||||
doc.node = nil
|
||||
doc.resp = nil
|
||||
}
|
||||
|
||||
// Close 关闭连接
|
||||
func (doc *htmlParser) Close() error {
|
||||
return doc.resp.Body.Close()
|
||||
}
|
||||
|
||||
// Getdoc 通过url获取网页内容
|
||||
func (doc *htmlParser) Getdoc(url string) (err error) {
|
||||
doc.resp, err = http.Get(url)
|
||||
defer doc.Close() // 关闭连接
|
||||
if doc.resp.StatusCode != http.StatusOK {
|
||||
err = fmt.Errorf("http get error: %s", doc.resp.Status)
|
||||
return err
|
||||
}
|
||||
doc.node, err = html.Parse(doc.resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("html parse error: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForEachNode 遍历节点
|
||||
func (doc *htmlParser) ForEachNode(n *html.Node, pre, post func(n *html.Node)) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
if pre != nil {
|
||||
pre(n)
|
||||
}
|
||||
doc.ForEachNode(n.FirstChild, pre, post)
|
||||
doc.ForEachNode(n.NextSibling, pre, post)
|
||||
if post != nil {
|
||||
post(n)
|
||||
}
|
||||
}
|
||||
|
||||
// SearchNode 搜索节点
|
||||
func (doc *htmlParser) SearchNode(tag string) []*html.Node {
|
||||
var nodes []*html.Node
|
||||
doc.ForEachNode(doc.node, func(n *html.Node) {
|
||||
if n.Type == html.ElementNode && n.Data == tag {
|
||||
nodes = append(nodes, n)
|
||||
}
|
||||
}, nil)
|
||||
return nodes
|
||||
}
|
||||
|
||||
// PrintAll 打印所有节点
|
||||
func (doc *htmlParser) PrintAll() {
|
||||
doc.ForEachNode(doc.node, func(n *html.Node) {
|
||||
if n.Type == html.ElementNode {
|
||||
fmt.Printf("%s\n", n.Data)
|
||||
}
|
||||
}, nil)
|
||||
}
|
||||
|
||||
// Show 是没有定义在接口中的方法,所以只能通过结构体实例调用
|
||||
func (doc *htmlParser) Show() {
|
||||
fmt.Println(doc.resp)
|
||||
fmt.Println()
|
||||
fmt.Println(doc.node)
|
||||
}
|
||||
func main() {
|
||||
var doc htmlParser
|
||||
doc.Getdoc("https://go.dev/")
|
||||
doc.Show()
|
||||
// 如果使用接口类型,则不能使用Show方法
|
||||
//var doc Html
|
||||
//doc.Getdoc("https://go.dev/")
|
||||
// 因为接口类型中没有定义Show方法,所以不能调用
|
||||
//doc.Show() // error, Show undefined (type Html has no field or method Show)
|
||||
|
||||
}
|
Loading…
Reference in New Issue