如何在Golang中编写简洁的代码

如何在Golang中编写简洁的代码 大家好。这个问题是关于如何编写整洁的代码。目前我正在尝试为我的国家制作一个新闻门户网站。我想从多个网站抓取数据来填充数据库。希望能帮助我规划一下代码的结构。我最近才开始用Go语言编程。所以任何帮助都会很有用。我目前的所有尝试都充斥着难以理解的硬编码。

func main() {
    fmt.Println("hello world")
}
2 回复

问题是如何编写干净的代码

如何编写“干净的代码”是一个广泛的主题,没有明确的答案。我认为你需要更具体一些。这里有一个资源链接

我想为数据库解析多个网站

这也有点模糊。我曾作为一个学习项目做过一些“多Go托管”。我惊讶于你只需要很少的Go代码行。大部分内容是用HTML、CSS和Javascript编写的。https://hosting.go4webdev.org

更多关于如何在Golang中编写简洁的代码的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中编写简洁代码的关键是遵循标准库的惯用模式,并合理组织代码结构。对于新闻抓取项目,建议采用以下结构:

// 定义清晰的数据结构
type Article struct {
    Title     string    `json:"title"`
    Content   string    `json:"content"`
    Source    string    `json:"source"`
    Published time.Time `json:"published"`
    URL       string    `json:"url"`
}

// 定义抓取器接口
type Fetcher interface {
    Fetch() ([]Article, error)
}

// 具体网站抓取器实现
type BBCFetcher struct {
    baseURL string
    timeout time.Duration
}

func (f *BBCFetcher) Fetch() ([]Article, error) {
    resp, err := http.Get(f.baseURL + "/news")
    if err != nil {
        return nil, fmt.Errorf("bbc fetch failed: %w", err)
    }
    defer resp.Body.Close()
    
    // 解析逻辑
    return f.parse(resp.Body)
}

func (f *BBCFetcher) parse(r io.Reader) ([]Article, error) {
    // 具体的HTML解析实现
    var articles []Article
    // ... 解析逻辑
    return articles, nil
}

// 数据库存储层
type Repository interface {
    Save(articles []Article) error
    GetLatest(count int) ([]Article, error)
}

type PostgresRepository struct {
    db *sql.DB
}

func (r *PostgresRepository) Save(articles []Article) error {
    tx, err := r.db.Begin()
    if err != nil {
        return err
    }
    defer tx.Rollback()
    
    stmt, err := tx.Prepare(`
        INSERT INTO articles (title, content, source, published, url) 
        VALUES ($1, $2, $3, $4, $5)
        ON CONFLICT (url) DO NOTHING`)
    if err != nil {
        return err
    }
    defer stmt.Close()
    
    for _, article := range articles {
        _, err := stmt.Exec(
            article.Title,
            article.Content,
            article.Source,
            article.Published,
            article.URL,
        )
        if err != nil {
            return err
        }
    }
    
    return tx.Commit()
}

// 主服务协调器
type NewsService struct {
    fetchers []Fetcher
    repo     Repository
}

func (s *NewsService) Run(ctx context.Context) error {
    var allArticles []Article
    
    for _, fetcher := range s.fetchers {
        articles, err := fetcher.Fetch()
        if err != nil {
            log.Printf("fetch error: %v", err)
            continue
        }
        allArticles = append(allArticles, articles...)
    }
    
    if err := s.repo.Save(allArticles); err != nil {
        return fmt.Errorf("save failed: %w", err)
    }
    
    return nil
}

// 配置驱动的初始化
func main() {
    cfg := loadConfig()
    
    db, err := sql.Open("postgres", cfg.DatabaseURL)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    service := &NewsService{
        fetchers: []Fetcher{
            &BBCFetcher{
                baseURL: "https://www.bbc.com",
                timeout: 30 * time.Second,
            },
            // 添加更多抓取器
        },
        repo: &PostgresRepository{db: db},
    }
    
    ctx := context.Background()
    if err := service.Run(ctx); err != nil {
        log.Fatal(err)
    }
}

这个结构通过接口解耦了数据获取、存储和业务逻辑,每个组件职责单一,便于测试和维护。使用配置管理外部依赖,避免硬编码。错误处理采用Go的惯用方式,通过%w包装错误上下文。

回到顶部