Golang은 다단계 주석을 구현합니다.

WBOY
풀어 주다: 2023-05-10 12:25:07
원래의
862명이 탐색했습니다.

소셜 미디어와 콘텐츠 플랫폼의 등장으로 다단계 댓글 시스템은 다양한 플랫폼에서 사용자 상호 작용과 커뮤니티 상호 작용을 위한 중요한 방법이 되었습니다. 다단계 댓글 시스템을 프론트엔드에서 구현하는 것은 상대적으로 간단하지만, 백엔드에서 구현하는 것은 상대적으로 복잡합니다. 이 기사에서는 golang을 사용하여 다단계 주석을 구현하는 방법을 소개합니다.

구현 아이디어

다단계 댓글은 실제로 트리 구조의 표시이며 각 댓글을 노드로 사용할 수 있습니다. 다단계 검토 시스템은 트리 구조의 기본 데이터 구조인 트리 및 이진 트리를 사용하여 구현할 수 있습니다. 이 기사에서는 구현을 위해 트리 구조의 이진 트리를 사용하기로 선택했습니다.

이진 트리의 노드는 왼쪽과 오른쪽 두 개의 자식 노드로 구성됩니다. 왼쪽 노드는 현재 노드의 첫 번째 자식 노드이고 오른쪽 노드는 현재 노드의 두 번째 자식 노드입니다. 따라서 댓글을 추가할 때마다 현재 댓글의 상위 노드와 왼쪽 및 오른쪽 하위 노드에만 주의하면 됩니다.

데이터베이스 디자인

다단계 댓글 시스템을 구현하려면 각 댓글의 상위-하위 관계를 데이터베이스에 저장해야 합니다. 일반적으로 트리 구조를 저장하는 데 두 가지 방법을 사용할 수 있습니다.

  1. 다중 테이블 연관 사용
  2. 단일 테이블에서 자체 참조 관계 사용

이 기사에서는 두 번째 방법, 즉 다음을 사용하기로 선택합니다. 단일 테이블에서 자체 참조 관계를 사용합니다.

댓글 테이블(댓글)의 구조는 다음과 같습니다.

CREATE TABLE `comment` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) DEFAULT NULL COMMENT '父级评论id',
  `content` varchar(255) DEFAULT NULL COMMENT '评论内容',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `parent_id` (`parent_id`),
  CONSTRAINT `comment_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `comment` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='评论表'
로그인 후 복사

위 테이블 구조에서 parent_id表示当前评论的父节点id,如果当前评论是一级评论,则parent_id为null。id为当前评论的id,content为评论内容,created_at는 생성 시간입니다.

코드 구현

데이터베이스 연결

먼저 데이터베이스에 연결하려면 golang에서 데이터베이스/sql 및 mysql 드라이버를 사용해야 합니다.

dsn := "root:123456@tcp(127.0.0.1:3306)/test"
db, err := sql.Open("mysql", dsn)
if err != nil {
   fmt.Printf("mysql connect error %s", err.Error())
   return
}
로그인 후 복사

댓글 삽입

댓글을 삽입할 때 현재 댓글이 현재 댓글인지 여부를 확인해야 합니다. 상위 노드 또는 하위 노드를 처리하는 데 사용됩니다.

현재 댓글이 상위 노드로 사용되는 경우 데이터베이스에 직접 삽입됩니다. 현재 댓글이 하위 노드인 경우 상위 노드의 오른쪽 노드를 업데이트해야 합니다.

// 添加评论
func AddComment(comment Comment) error {
   if comment.ParentID == 0 {
       _, err := db.Exec("INSERT INTO comment(parent_id, content, created_at) VALUES(?, ?, ?)", nil, comment.Content, comment.CreatedAt)
       if err != nil {
           return err
       }
   } else {
       var rightNode *int
       err := db.QueryRow("SELECT right_node FROM comment WHERE id = ?", comment.ParentID).Scan(&rightNode)
       if err != nil {
           return err
       }
       tx, err := db.Begin()
       if err != nil {
           return err
       }
       // 更新右节点
       _, err = tx.Exec("UPDATE comment SET right_node = right_node + 2 WHERE right_node > ?", rightNode)
       if err != nil {
           tx.Rollback()
           return err
       }
       _, err = tx.Exec("UPDATE comment SET left_node = left_node + 2 WHERE left_node > ?", rightNode)
       if err != nil {
           tx.Rollback()
           return err
       }
       _, err = tx.Exec("INSERT INTO comment(parent_id, left_node, right_node, content, created_at) VALUES(?, ?, ?, ?, ?)", comment.ParentID, rightNode, rightNode+1, comment.Content, comment.CreatedAt)
       if err != nil {
           tx.Rollback()
           return err
       }
       tx.Commit()
   }
   return nil
}
로그인 후 복사

댓글 쿼리

댓글을 쿼리할 때 노드의 왼쪽, 오른쪽 순서에 따라 정렬해야 트리 구조의 댓글 목록을 얻을 수 있습니다. 댓글을 질의할 때 왼쪽, 오른쪽 노드를 이용하여 정렬해야 하므로 쿼리 조건에 왼쪽, 오른쪽 노드 열을 추가해야 합니다. 또한 프런트엔드 표시를 용이하게 하기 위해 현재 노드가 어떤 노드 레벨인지 나타내기 위해 레벨 필드를 사용해야 합니다.

type Comment struct {
   ID        int    `json:"id"`
   ParentID  int    `json:"parent_id"`
   Content   string `json:"content"`
   LeftNode  int    `json:"left_node"`
   RightNode int    `json:"right_node"`
   Level     int    `json:"level"`
   CreatedAt string `json:"created_at"`
}

// 获取评论列表
func GetComments() ([]Comment, error) {
   rows, err := db.Query("SELECT id, parent_id, content, created_at, left_node, right_node, (COUNT (parent.id) -1) AS level FROM comment AS node, comment AS parent WHERE node.left_node BETWEEN parent.left_node AND parent.right_node GROUP BY node.id ORDER BY left_node")
   if err != nil {
       return nil, err
   }
   defer rows.Close()

   var comments []Comment
   for rows.Next() {
       var comment Comment
       err := rows.Scan(&comment.ID, &comment.ParentID, &comment.Content, &comment.CreatedAt, &comment.LeftNode, &comment.RightNode, &comment.Level)
       if err != nil {
           return nil, err
       }
       comments = append(comments, comment)
   }
   return comments, nil
}
로그인 후 복사

댓글 삭제

댓글을 삭제할 때는 현재 댓글이 상위 노드인지, 하위 노드인지 확인해야 합니다. 상위 노드인 경우 하위 트리 전체를 삭제해야 합니다.

// 删除评论
func DeleteComment(id int) error {
   tx, err := db.Begin()
   if err != nil {
       return err
   }
   var leftNode int
   var rightNode int
   err = tx.QueryRow("SELECT left_node, right_node FROM comment WHERE id = ?", id).Scan(&leftNode, &rightNode)
   if err != nil {
       tx.Rollback()
       return err
   }
   if leftNode == 1 && rightNode > 1 {
       // 删除子树
       _, err = tx.Exec("DELETE FROM comment WHERE left_node >= ? AND right_node <= ?;", leftNode, rightNode)
       if err != nil {
           tx.Rollback()
           return err
       }
       err = tx.Commit()
       if err != nil {
           tx.Rollback()
           return err
       }
   } else {
       // 删除单个节点
       _, err = tx.Exec("DELETE FROM comment WHERE id = ?", id)
       if err != nil {
           tx.Rollback()
           return err
       }
       err = tx.Commit()
       if err != nil {
           tx.Rollback()
           return err
       }
   }
   return nil
}
로그인 후 복사

결론

위의 코드 구현을 통해 우리는 모든 기능을 갖춘 다단계 댓글 시스템을 빠르게 구축할 수 있습니다. 물론 이는 단지 기본적인 구현 방법일 뿐이며, 실제 시나리오에서는 특정 요구에 따라 해당 최적화 및 확장이 이루어져야 합니다.

위 내용은 Golang은 다단계 주석을 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!