【Go语言学习系列18】标准库探索(五):HTTP客户端

Go语言中创建HTTP客户端 利用Go语言创建HTTP客户端 阅读详情

📚 原创系列: “Go语言学习系列”

🔄 转载说明: 本文最初发布于"Gopher部落"微信公众号,经原作者授权转载。

🔗 关注原创: 欢迎扫描文末二维码,关注"Gopher部落"微信公众号获取第一手Go技术文章。

📑 Go语言学习系列导航

本文是【Go语言学习系列】的第18篇,当前位于第二阶段(基础巩固篇)

🚀 第二阶段:基础巩固篇
  1. 13-包管理深入理解
  2. 14-标准库探索(一):io与文件操作
  3. 15-标准库探索(二):字符串处理
  4. 16-标准库探索(三):时间与日期
  5. 17-标准库探索(四):JSON处理
  6. 18-标准库探索(五):HTTP客户端 👈 当前位置
  7. 19-标准库探索(六):HTTP服务器
  8. 20-单元测试基础
  9. 21-基准测试与性能剖析入门
  10. 22-反射机制基础
  11. 23-Go中的面向对象编程
  12. 24-函数式编程在Go中的应用
  13. 25-context包详解
  14. 26-依赖注入与控制反转
  15. 27-第二阶段项目实战:RESTful API服务

📚 查看完整Go语言学习系列导航

📖 文章导读

在本文中,您将了解:

  • Go语言HTTP客户端的基本使用方法
  • 发送各种HTTP请求(GET、POST、PUT、DELETE等)
  • 处理和解析HTTP响应
  • 配置和优化HTTP客户端
  • 文件上传与下载的实现
  • HTTP客户端性能优化的最佳实践

Go语言的net/http包不仅提供了HTTP服务器功能,还包含了功能强大的HTTP客户端API,让我们能够轻松地与各种Web服务进行交互。本文将深入探讨这些API的使用方法,帮助您掌握在Go中构建高效可靠的HTTP客户端的技巧。

1. HTTP客户端基础

在Go中,net/http包提供了HTTP客户端和服务器实现。本文我们将重点介绍其客户端功能。

1.1 简单的GET请求

Go标准库使发送HTTP请求变得异常简单。以下是发送GET请求的基本方式:

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
)

func main() {
    // 发送GET请求
    resp, err := http.Get("https://api.github.com/users/golang")
    if err != nil {
        log.Fatalf("请求失败: %v", err)
    }
    defer resp.Body.Close() // 确保响应体被关闭
    
    // 读取响应体
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        log.Fatalf("读取响应失败: %v", err)
    }
    
    // 打印状态码和响应体
    fmt.Printf("状态码: %d\n", resp.StatusCode)
    fmt.Printf("响应体: %s\n", body)
}

这个简单的例子展示了Go的HTTP客户端最基本的用法。让我们详细分析:

  1. http.Get函数发送GET请求并返回响应和可能的错误
  2. 使用defer resp.Body.Close()确保资源被正确释放
  3. io.ReadAll读取整个响应体
  4. 可以通过resp.StatusCode获取HTTP状态码

1.2 其他HTTP方法

除了GET,Go还支持所有标准HTTP方法:

// POST请求
resp, err := http.Post("https://httpbin.org/post", "application/json", 
                       strings.NewReader(`{"name":"gopher","message":"hello"}`))

// PUT请求
req, err := http.NewRequest(http.MethodPut, "https://httpbin.org/put", 
                           strings.NewReader(`{"name":"gopher","status":"updated"}`))
client := &http.Client{}
resp, err := client.Do(req)

// DELETE请求
req, err := http.NewRequest(http.MethodDelete, "https://httpbin.org/delete?id=123", nil)
resp, err := client.Do(req)

1.3 请求头与请求参数

设置请求头和URL参数是常见需求:

// 创建请求
req, err := http.NewRequest("GET", "https://api.example.com/users", nil)
if err != nil {
    log.Fatal(err)
}

// 添加请求头
req.Header.Add("Authorization", "Bearer token123456")
req.Header.Add("Content-Type", "application/json")
req.Header.Add("User-Agent", "GoHTTPClient/1.0")

// 添加URL参数
q := req.URL.Query()
q.Add("page", "1")
q.Add("limit", "10")
q.Add("sort", "created_at")
req.URL.RawQuery = q.Encode()

// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
// ...处理响应

2. 处理HTTP响应

2.1 读取响应体

处理HTTP响应的核心是正确读取响应体。前面我们已经看到了使用io.ReadAll的方式,但还有其他模式:

// 分块读取大型响应
resp, err := http.Get("https://example.com/large-file")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

// 使用缓冲读取
buf := make([]byte, 1024)
for {
    n, err := resp.Body.Read(buf)
    if err == io.EOF {
        break // 读取完成
    }
    if err != nil {
        log.Fatal(err)
    }
    
    // 处理读取的部分数据
    fmt.Printf("读取了 %d 字节的数据\n", n)
    fmt.Printf("数据片段: %s\n", buf[:n])
}

对于结构化数据(如JSON),可以直接解码:

// 解码JSON响应
resp, err := http.Get("https://api.github.com/users/golang")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

var user struct {
    Login   string `json:"login"`
    ID      int    `json:"id"`
    Name    string `json:"name"`
    Bio     string `json:"bio"`
    Public  struct {
        Repos int `json:"public_repos"`
    } `json:"public_repos"`
}

if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
    log.Fatal(err)
}

fmt.Printf("用户信息: %+v\n", user)

2.2 处理状态码

HTTP响应的状态码表明请求的结果:

resp, err := http.Get("https://example.com/api/resource")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

switch resp.StatusCode {
case http.StatusOK, http.StatusCreated, http.StatusAccepted:
    // 请求成功
    fmt.Println("请求成功!")
    // 处理响应...
    
case http.StatusNotFound:
    fmt.Println("资源不存在")
    
case http.StatusUnauthorized, http.StatusForbidden:
    fmt.Println("认证或授权失败")
    
case http.StatusInternalServerError:
    fmt.Println("服务器错误")
    
default:
    fmt.Printf("未预期的状态码: %d\n", resp.StatusCode)
}

2.3 处理响应头

响应头包含有用的元数据:

resp, err := http.Get("https://example.com")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

// 获取特定响应头
contentType := resp.Header.Get("Content-Type")
fmt.Printf("内容类型: %s\n", contentType)

// 遍历所有响应头
fmt.Println("所有响应头:")
for name, values := range resp.Header {
    for _, value := range values {
        fmt.Printf("%s: %s\n", name, value)
    }
}

// 检查响应是否支持压缩
if resp.Header.Get("Content-Encoding") == "gzip" {
    // 处理gzip压缩内容
    reader, err := gzip.NewReader(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    defer reader.Close()
    // 从解压缩的reader读取内容
    body, err := io.ReadAll(reader)
    // ...
}

3. 高级HTTP客户端配置

3.1 自定义HTTP客户端

标准库的默认HTTP客户端适用于大多数场景,但可以自定义:

client := &http.Client{
    // 设置超时时间
    Timeout: 10 * time.Second,
    
    // 自定义重定向策略
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
        // 限制最多重定向3次
        if len(via) >= 3 {
            return fmt.Errorf("停止重定向:已达到最大重定向次数")
        }
        return nil
    },
}

// 使用自定义客户端发送请求
resp, err := client.Get("https://example.com")
// ...

3.2 传输层配置(Transport)

更深层次的设置可以通过自定义Transport实现:

transport := &http.Transport{
    // 代理设置
    Proxy: http.ProxyURL(&url.URL{
        Scheme: "http",
        Host:   "proxy.example.com:8080",
    }),
    
    // TLS配置
    TLSClientConfig: &tls.Config{
        InsecureSkipVerify: false, // 生产环境请设为false
        MinVersion:         tls.VersionTLS12,
    },
    
    // 连接池设置
    MaxIdleConns:        100,
    MaxIdleConnsPerHost: 10,
    IdleConnTimeout:     90 * time.Second,
    
    // 拨号设置
    DialContext: (&net.Dialer{
        Timeout:   30 * time.Second,
        KeepAlive: 30 * time.Second,
    }).DialContext,
    
    // HTTP/2支持
    ForceAttemptHTTP2: true,
}

client := &http.Client{
    Transport: transport,
    Timeout:   15 * time.Second,
}

// 使用配置后的客户端
resp, err := client.Get("https://example.com")
// ...

3.3 请求上下文(Context)

使用context可以实现请求取消和超时控制:

import (
    "context"
    "net/http"
    "time"
)

func main() {
    // 创建一个5秒超时的上下文
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel() // 确保取消函数被调用
    
    // 创建带上下文的请求
    req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil)
    if err != nil {
        log.Fatal(err)
    }
    
    // 发送请求
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        // 检查是否因超时而失败
        if ctx.Err() == context.DeadlineExceeded {
            log.Println("请求超时")
        } else {
            log.Printf("请求失败: %v", err)
        }
        return
    }
    defer resp.Body.Close()
    
    // 处理响应
    // ...
}

4. 高级HTTP请求

4.1 表单提交

提交HTML表单数据:

// 创建表单数据
formData := url.Values{
    "username": {"gopher"},
    "email":    {"gopher@example.com"},
    "message":  {"Hello from Go!"},
}

// 发送表单
resp, err := http.PostForm("https://httpbin.org/post", formData)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

// 处理响应
body, err := io.ReadAll(resp.Body)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("响应: %s\n", body)

4.2 multipart/form-data和文件上传

上传文件需要使用multipart/form-data格式:

// 打开要上传的文件
file, err := os.Open("example.jpg")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

// 创建multipart写入器
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)

// 创建文件表单字段
part, err := writer.CreateFormFile("file", filepath.Base(file.Name()))
if err != nil {
    log.Fatal(err)
}

// 复制文件内容到表单字段
if _, err = io.Copy(part, file); err != nil {
    log.Fatal(err)
}

// 添加额外的文本字段
writer.WriteField("description", "示例图片上传")
writer.WriteField("category", "测试")

// 完成写入
writer.Close()

// 创建请求
req, err := http.NewRequest("POST", "https://httpbin.org/post", body)
if err != nil {
    log.Fatal(err)
}

// 设置Content-Type头,指定boundary
req.Header.Set("Content-Type", writer.FormDataContentType())

// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

// 处理响应
// ...

4.3 处理cookies

Cookie处理在Web请求中很常见:

// 创建HTTP客户端,启用cookie jar
jar, err := cookiejar.New(nil)
if err != nil {
    log.Fatal(err)
}

client := &http.Client{
    Jar: jar,
}

// 发送第一个请求,服务器可能会设置cookie
resp, err := client.Get("https://httpbin.org/cookies/set?name=value")
if err != nil {
    log.Fatal(err)
}
resp.Body.Close() // 关闭但不处理响应

// 发送第二个请求,Jar自动附带上一个响应的cookie
resp, err = client.Get("https://httpbin.org/cookies")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

// 读取响应,应当显示服务器收到的cookie
body, err := io.ReadAll(resp.Body)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("响应: %s\n", body)

// 手动添加cookie到请求
req, err := http.NewRequest("GET", "https://httpbin.org/cookies", nil)
if err != nil {
    log.Fatal(err)
}
req.AddCookie(&http.Cookie{
    Name:  "custom_cookie",
    Value: "custom_value",
})
resp, err = client.Do(req)
// ...

5. 构建可重用的HTTP客户端

5.1 创建API客户端结构

对于重复调用同一API,创建专用客户端结构是最佳实践:

// APIClient 封装API调用功能
type APIClient struct {
    BaseURL    string
    HTTPClient *http.Client
    Token      string
}

// NewAPIClient 创建新的API客户端
func NewAPIClient(baseURL, token string) *APIClient {
    return &APIClient{
        BaseURL: baseURL,
        HTTPClient: &http.Client{
            Timeout: 10 * time.Second,
        },
        Token: token,
    }
}

// Get 发送GET请求到指定路径
func (c *APIClient) Get(path string, params map[string]string) ([]byte, error) {
    // 构建完整URL
    u, err := url.Parse(c.BaseURL)
    if err != nil {
        return nil, err
    }
    u.Path = path
    
    // 添加查询参数
    q := u.Query()
    for key, value := range params {
        q.Add(key, value)
    }
    u.RawQuery = q.Encode()
    
    // 创建请求
    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        return nil, err
    }
    
    // 添加认证头
    req.Header.Add("Authorization", "Bearer "+c.Token)
    req.Header.Add("Content-Type", "application/json")
    
    // 发送请求
    resp, err := c.HTTPClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    // 检查状态码
    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
        return nil, fmt.Errorf("API错误: %d %s", resp.StatusCode, resp.Status)
    }
    
    // 读取并返回响应体
    return io.ReadAll(resp.Body)
}

// Post 发送POST请求到指定路径
func (c *APIClient) Post(path string, data interface{}) ([]byte, error) {
    // 将数据编码为JSON
    jsonData, err := json.Marshal(data)
    if err != nil {
        return nil, err
    }
    
    // 创建请求
    u, err := url.Parse(c.BaseURL)
    if err != nil {
        return nil, err
    }
    u.Path = path
    
    req, err := http.NewRequest("POST", u.String(), bytes.NewBuffer(jsonData))
    if err != nil {
        return nil, err
    }
    
    // 添加头
    req.Header.Add("Authorization", "Bearer "+c.Token)
    req.Header.Add("Content-Type", "application/json")
    
    // 发送请求
    resp, err := c.HTTPClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    // 检查状态码
    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
        return nil, fmt.Errorf("API错误: %d %s", resp.StatusCode, resp.Status)
    }
    
    // 读取并返回响应体
    return io.ReadAll(resp.Body)
}

使用此客户端:

// 创建客户端
client := NewAPIClient("https://api.example.com", "your-api-token")

// 获取用户列表
params := map[string]string{
    "page":  "1",
    "limit": "10",
}
data, err := client.Get("/users", params)
if err != nil {
    log.Fatalf("获取用户失败: %v", err)
}
fmt.Printf("用户数据: %s\n", data)

// 创建新用户
newUser := map[string]interface{}{
    "name":  "New User",
    "email": "newuser@example.com",
    "role":  "user",
}
response, err := client.Post("/users", newUser)
if err != nil {
    log.Fatalf("创建用户失败: %v", err)
}
fmt.Printf("创建响应: %s\n", response)

6. 性能优化与最佳实践

6.1 连接池与客户端重用

Go的http.Client内部使用连接池机制来提高性能:

// 创建一个全局的HTTP客户端,整个应用程序共享
var client = &http.Client{
    Timeout: 10 * time.Second,
    Transport: &http.Transport{
        MaxIdleConns:        100,              // 连接池中的最大空闲连接数
        MaxIdleConnsPerHost: 10,               // 每个主机的最大空闲连接数
        IdleConnTimeout:     90 * time.Second, // 空闲连接超时时间
    },
}

// 在应用中重复使用此客户端
func fetchURL(url string) ([]byte, error) {
    resp, err := client.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    return io.ReadAll(resp.Body)
}

一些关键的性能优化点:

  1. 避免为每个请求创建新的http.Client
  2. 配置适当的空闲连接数量和超时时间
  3. 确保始终关闭响应体,即使不读取它

6.2 请求超时设置

为避免请求卡住,始终设置合理的超时时间:

client := &http.Client{
    // 设置整体请求超时(包括连接、重定向和读取响应体)
    Timeout: 10 * time.Second,
    Transport: &http.Transport{
        // 仅连接建立的超时
        DialContext: (&net.Dialer{
            Timeout: 5 * time.Second,
        }).DialContext,
        // TLS握手超时
        TLSHandshakeTimeout: 5 * time.Second,
        // 响应头超时
        ResponseHeaderTimeout: 5 * time.Second,
        // 空闲连接超时
        IdleConnTimeout: 90 * time.Second,
    },
}

6.3 并发请求处理

使用goroutine和channel处理并发请求:

func fetchConcurrent(urls []string) []Result {
    ch := make(chan Result, len(urls))
    var wg sync.WaitGroup
    
    // 限制最大并发数
    semaphore := make(chan struct{}, 10)
    
    for _, url := range urls {
        wg.Add(1)
        go func(url string) {
            defer wg.Done()
            
            // 获取信号量
            semaphore <- struct{}{}
            defer func() { <-semaphore }()
            
            // 发送请求
            resp, err := http.Get(url)
            if err != nil {
                ch <- Result{URL: url, Error: err}
                return
            }
            defer resp.Body.Close()
            
            // 读取响应
            body, err := io.ReadAll(resp.Body)
            if err != nil {
                ch <- Result{URL: url, Error: err}
                return
            }
            
            ch <- Result{URL: url, Body: body}
        }(url)
    }
    
    // 等待所有请求完成并关闭通道
    go func() {
        wg.Wait()
        close(ch)
    }()
    
    // 收集结果
    var results []Result
    for result := range ch {
        results = append(results, result)
    }
    
    return results
}

type Result struct {
    URL   string
    Body  []byte
    Error error
}

6.4 HTTP/2支持

Go的net/http包自动支持HTTP/2,但可以通过配置优化:

client := &http.Client{
    Transport: &http.Transport{
        // 启用HTTP/2
        ForceAttemptHTTP2: true,
        // HTTP/2连接设置
        MaxIdleConnsPerHost: 100,
    },
}

6.5 响应体流式处理

处理大响应时,使用流式处理避免内存占用过高:

// 下载大文件
func downloadLargeFile(url, destPath string) error {
    // 创建目标文件
    out, err := os.Create(destPath)
    if err != nil {
        return err
    }
    defer out.Close()
    
    // 发送GET请求
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    
    // 检查状态码
    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("下载失败,状态码: %d", resp.StatusCode)
    }
    
    // 创建进度条(可选)
    fileSize := resp.ContentLength
    progress := 0
    counter := &WriteCounter{
        Total: fileSize,
    }
    
    // 使用io.Copy将响应体直接流式复制到文件
    _, err = io.Copy(out, io.TeeReader(resp.Body, counter))
    if err != nil {
        return err
    }
    
    return nil
}

// WriteCounter 用于跟踪下载进度
type WriteCounter struct {
    Total     int64
    Downloaded int64
}

func (wc *WriteCounter) Write(p []byte) (int, error) {
    n := len(p)
    wc.Downloaded += int64(n)
    wc.PrintProgress()
    return n, nil
}

func (wc *WriteCounter) PrintProgress() {
    if wc.Total <= 0 {
        fmt.Printf("\r下载中: %d bytes", wc.Downloaded)
        return
    }
    
    percentage := float64(wc.Downloaded) / float64(wc.Total) * 100
    fmt.Printf("\r下载进度: %.2f%% (%d/%d bytes)", percentage, wc.Downloaded, wc.Total)
}

7. 总结与展望 🔍

在本文中,我们深入探讨了Go语言中的HTTP客户端功能,从基本概念到高级应用。Go的net/http包为我们提供了强大而灵活的HTTP客户端功能,使构建可靠的网络应用变得简单。

我们学习了:

  1. 基本的HTTP请求发送方法
  2. 如何处理响应和错误
  3. 定制HTTP客户端配置
  4. 处理表单和文件上传
  5. 构建可重用的API客户端结构
  6. 性能优化和最佳实践

对于现代Go开发者来说,掌握HTTP客户端编程是必不可少的技能。无论是构建API客户端、微服务间通信还是简单的数据抓取,这些知识都将派上用场。

在接下来的文章中,我们将探索Go标准库中的HTTP服务器部分,学习如何构建高性能的Web服务。


👨‍💻 关于作者与Gopher部落

"Gopher部落"专注于Go语言技术分享,提供从入门到精通的完整学习路线。

🌟 为什么关注我们?

  1. 系统化学习路径:从入门基础到高级特性,循序渐进掌握Go开发
  2. 实战驱动教学:理论结合实践,每篇文章都有可操作的代码示例
  3. 持续更新内容:定期分享最新Go生态技术动态与大厂实践经验
  4. 专业技术社区:加入我们的技术交流群,与众多Go开发者共同成长

📱 关注方式

  1. 微信公众号:搜索 “Gopher部落” 或 “GopherTribe”
  2. 优快云专栏:点击页面右上角"关注"按钮

💡 读者福利

关注公众号回复 “HTTP客户端” 即可获取:

  • 完整示例代码
  • HTTP客户端常见问题与解决方案
  • Go API开发最佳实践指南

期待与您在Go语言的学习旅程中共同成长!

Go 学习笔记(76)— Go 标准库 net/http 创建客户端(发送 GET、POST 请求) 1. Get 请求 1.1 使用 net/http 包的快捷方法 GET package main import ( "fmt" "io/ioutil" "net/http" ) func main() { resp, err := http.Get("http://www.baidu.com") if err != nil { fmt.Println(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp 阅读详情

相关推荐

如何优化Silvaco二极管仿真网格?这些参数设置技巧让你的结果更精确

本文详细介绍了如何优化Silvaco二极管仿真网格,通过精细调整网格参数提升仿真精度。重点解析了网格密度与计算精度的权衡、关键区域识别与网格强化策略,以及掺杂分布与网格适配技术,帮助工程师在半导体器件仿真中获得更准确的结果。

t8u9v0w1x的博客 660

go基础 go的HTTP网络编程

go的http编程有如下优点: Go原生支持http, import(“net/http”) Go的http服务性能和nginx比较接近 几行代码就可以实现一个web服务 http编程示例

一越王超的博客 7424

Seedance2.5本地部署:从环境配置到批量生图的工程实践指南

最近在几个技术社群里,看到不少人在讨论 AI 生图和视频工具。有人抱怨在线服务要么贵、要么慢、要么生成内容受限;也有人尝试了各种“免费”方案,结果不是功能残缺就是暗藏收费陷阱。就在大家觉得“又好又免费”的本地部署方案门槛太高时,Seedance2.5 突然冒了出来,而且口号相当直接:本地部署、完全免费、不联网、功能对标甚至超越一些付费产品。 但这类宣传我们见多了,真正的问题是:它到底能不能在普通开发者的机器上跑起来?生成质量是否真的可用?长期使用会不会遇到模型崩溃、依赖冲突或者资源爆炸?更重要的是,对于一个

weixin_27419879的博客 1131

【Go入门】 Go的http包详解

我们前面小节讲述conn.server的时候,其实内部是调用了http包默认的路由器,通过路由器把本次请求的信息传递到了后端的处理函数。那么这个路由器是怎么实现的呢?mu sync.RWMutex //锁,由于请求涉及到并发处理,因此这里需要一个锁机制m map[string]muxEntry // 路由规则,一个string对应一个mux实体,这里的string就是注册的路由表达式hosts bool // 是否在任意的规则中带有host信息下面看一下muxEntry。

QAQterrible的博客 1770

结构光三维重建(一)条纹结构光三维重建

在近景三维重建领域,结构光技术可以说是应用最广泛的,尤其在工业领域。该技术目前具有高精度和无视弱纹理等优点,但复杂的室外环境还是会对该技术造成一定程度的干扰。目前用的比较多的结构光分别两大类:线结构光以及条纹结构光。接下来我先来简单介绍一下条纹结构光三维重建,事实上,条纹结构光的原理与双目立体匹配是非常相似的。...

AAAA202012的博客 1万+

MOOS-ivp 实验一 MOOS软件的安装与执行

MOOS-ivp实验一 实验一步骤总结 文章目录MOOS-ivp实验一前言一、实验一1.下载软件2.安装必要的插件3.安装后检查4.路径添加5.执行示例文件总结 前言 在moos学习过程中,我觉得最好把学习的每一步骤都总结一下,方便日后进行回顾。moos官网设置了十八个实验,涉及到了moos的各个方面,完成这些实验也是moos入门的好办法。 一、实验一 实验一主要内容仅仅是软件的安装,仅仅这一步就花费了我接近两天的时间。主要问题发生在linux系统的配置问题上。 1.下载软件 svn co https:

weixin_44151170的博客 6670

golang常用库之http客户端-Sling、标准库net/http包 | go标准库mime/multipart

golang http客户端 golang net/http包 golang的net/http包已经提供了强大了网络操作函数。 golang使用http client发起get和post请求示例

西京刀客 8285

Excel也能玩转K-means聚类?手把手教你用表格搞定用户分群(附完整公式)

本文详细介绍了如何在Excel中实现K-means聚类算法,无需编程即可完成用户分群。通过SUMIF、SQRT等基础函数,从数据预处理到最终分群全流程手把手教学,特别强调数据标准化和迭代优化的关键步骤,帮助运营团队低成本高效分析用户行为数据。

weixin_30555125的博客 181

【Go语言学习系列16】标准库探索(三):时间与日期

本文深入讲解Go语言标准库中time包的使用,包括时间的表示、格式化、解析、计算、比较,以及定时器和计时器的应用。通过实例说明如何在Go项目中高效处理时间与日期相关问题。

GopherTribe的博客 1386

Vivado报错-4 [Routed 35-3424] SLL Assignment failed ILP VU19P

Vivado报错[Routed 35-3424] SLL Assignment failed ILP VU19P

weixin_39896700的博客 1409

【Android 教程系列第 30 篇】为什么要为 App 应用加固 ?如何为 App 应用加固 ?

一:为什么要为 App 应用加固 ? 二:如何为 App 应用加固 ? 三:加固后为什么要重新签名 ?

“Allen Su”的博客 7053

【Go语言学习系列14】标准库探索(一):io与文件操作

深入讲解Go语言io包与文件操作,从Reader/Writer接口到实际文件处理案例,全面掌握Go的IO处理机制

GopherTribe的博客 882

为什么devc++编译项目会失败?提示gcc无法正常启动...

根据你的描述,编译能正常进行时,只打开源文件并没有问题,问题主要出现在创建项目后编译失败,这通常与 Makefile 配置、环境变量、编译器路径设置等因素有关。你可以检查 Makefile 配置,验证 DevC++ 的编译器环境设置,或者尝试清理并重新配置项目。如果问题仍然存在,可以尝试重装 DevC++ 或重新配置工具链。希望如上措施及解决方案能够帮到有需要的你。

**My Coding Family** 1376

【Go语言学习系列19】标准库探索(六):HTTP服务器

全面解析Go语言HTTP服务器开发,从基础路由到高级中间件,掌握高性能Web服务构建技巧

GopherTribe的博客 1158

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【Go语言学习系列15】标准库探索(二):字符串处理

深入讲解Go语言io包与文件操作,从Reader/本文深入探讨Go语言标准库中的字符串处理功能,包括strings、strconv及unicode包的使用方法。通过实例讲解常见字符串操作,帮助读者全面掌握Go中的文本处理能力,提高字符串处理效率和代码质量。Writer接口到实际文件处理案例,全面掌握Go的IO处理机制

GopherTribe的博客 1088

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【Go语言学习系列00】Go语言学习系列导航

本文是Go语言学习系列的导航文档,提供了从入门到精通的学习路径,包含各阶段文章链接和内容概述,帮助读者系统化学习Go语言。

GopherTribe的博客 1575

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【Go语言学习系列17】标准库探索(四):JSON处理

本文深入介绍Go语言标准库中的JSON处理功能,包括基本序列化与反序列化、自定义编码/解码、处理复杂数据结构等高级特性。通过丰富的实例讲解如何高效处理JSON数据,帮助开发者在Go项目中灵活应用JSON技术。

GopherTribe的博客 1114

第 18 章 - Golang 标准库概览

fmt:用于格式化输入输出,是进行打印输出和字符串格式化的基础。os:提供了操作系统交互的功能,如文件操作、环境变量获取等。net/http:实现HTTP客户端和服务端的功能,是Web开发的基础。sync:提供了一些基本的同步原语,如互斥锁、条件变量等,对于编写多线程安全的程序非常重要。log:提供了简单的日志记录功能,方便调试和追踪程序运行状态。time:提供了时间日期相关的操作,包括获取当前时间、定时器等。strings:提供了字符串处理的各种方法,如查找、替换、分割等。sort。

hummhumm的专栏 1291

golang笔记13--go语言 http 及其它标准库

golang笔记13--go语言 http 及其它标准库1 介绍2 http及其它标准库2.1 http 标准库2.2 其它标准库2.3 gin 框架介绍2.4 为 gin 增加 middleware3 注意事项4 说明 1 介绍 本文继上文 golang笔记12–迷宫的广度优先搜索, 进一步了解 go 语言 http 及其它标准库,以及相应注意事项。 具体包括: http 标准库、其它标准库、gin 框架介绍、为 gin 增加 middleware 等内容。 2 http及其它标准库 2.1 http

脚步不能达到的地方,眼光可以达到;眼光不能达到的地方,精神可以飞到 583

【Go语言学习系列20】单元测试基础

掌握Go语言单元测试技巧,从基础语法到高级模式,全面提升测试质量与代码可靠性

GopherTribe的博客 848

【Go语言学习系列22】反射机制基础

深入解析Go语言反射机制,从基础概念到高级应用,全面掌握reflect包的使用技巧与性能注意事项

GopherTribe的博客 978

【Go语言学习系列25】context包详解

深入解析Go语言context包的设计理念与使用方法,掌握goroutine取消、超时控制与请求范围数据传递的最佳实践

GopherTribe的博客 1352

【Go语言学习系列13】包管理深入理解

深入解析Go Modules的工作原理,掌握go.mod与go.sum文件管理,学习私有模块配置和依赖版本控制的最佳实践

GopherTribe的博客 1143

【Go语言学习系列27】第二阶段项目实战:RESTful API服务

从零开始构建完整的Go语言RESTful API服务,集成数据库、认证、日志与监控,打造专业级后端应用

GopherTribe的博客 1099

Go语言标准库之net_http

目录 一、net/http介绍 1.1 HTTP协议 二、HTTP客户端 2.1 基本的HTTP/HTTPS请求 2.2 GET请求示例 2.3 带参数的GET请求示例 2.4 Post请求示例 2.5 自...

weixin_30470643的博客 243

【Go语言学习系列21】基准测试与性能剖析入门

掌握Go语言性能测试与剖析技术,从基准测试到内存分析,全方位提升程序性能

GopherTribe的博客 698
上一篇: 【Go语言学习系列17】标准库探索(四):JSON处理
下一篇: 【Go语言学习系列19】标准库探索(六):HTTP服务器
Gopher部落
博客等级 码龄2年 784粉丝 92原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gopher部落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值