Làm thế nào để kiểm tra một cấu trúc trống?


110

Tôi xác định một cấu trúc ...

type Session struct {
    playerId string
    beehive string
    timestamp time.Time
}

Đôi khi tôi chỉ định một phiên trống cho nó (vì không thể thực hiện được)

session = Session{};

Sau đó, tôi muốn kiểm tra, nếu nó trống:

if session == Session{} {
     // do stuff...
}

Rõ ràng là điều này không hoạt động. Làm thế nào để tôi viết nó?


4
Phiên {} không phải là phiên "trống"; nó được khởi tạo với mỗi trường là giá trị 0.
Paul Hankin

Câu trả lời:


177

Bạn có thể sử dụng == để so sánh với ký tự tổng hợp giá trị 0 vì tất cả các trường đều có thể so sánh được :

if (Session{}) == session  {
    fmt.Println("is zero value")
}

sân chơi ví dụ

Do sự không rõ ràng về phân tích cú pháp , các dấu ngoặc đơn được yêu cầu xung quanh chữ tổng hợp trong điều kiện if.

Việc sử dụng ==ở trên áp dụng cho các cấu trúc trong đó tất cả các trường đều có thể so sánh được . Nếu cấu trúc chứa trường không thể so sánh (lát cắt, bản đồ hoặc hàm), thì các trường đó phải được so sánh từng trường một với giá trị 0 của chúng.

Một cách khác để so sánh toàn bộ giá trị là so sánh một trường phải được đặt thành giá trị khác 0 trong một phiên hợp lệ. Ví dụ: nếu id người chơi phải là! = "" Trong một phiên hợp lệ, hãy sử dụng

if session.playerId == "" {
    fmt.Println("is zero value")
}

4
@kristen Tham khảo con trỏ và so sánh. Nếu sessionkhông phải là nil *Session, thì hãy sử dụng if (Session{} == *session {.
Muffin Top,

3
Vì vậy, tôi gặp lỗi, struct containing []byte cannot be comparedbởi vì, tốt, cấu trúc của tôi chứa một lát byte.
Nevermore

14
@Nevermore Câu trả lời áp dụng cho một cấu trúc có các trường có thể so sánh được. Nếu cấu trúc của bạn chứa các giá trị không thể so sánh như byte [], thì bạn cần viết mã để kiểm tra tất cả các trường hoặc sử dụng gói phản ánh như được nêu trong một câu trả lời khác.
Muffin hàng đầu,

2
Như đã đề cập bởi @Nevermore, ==so sánh với các trường lát cắt sẽ không thành công. Để so sánh các cấu trúc, sử dụng một trong hai reflect.DeepEqualhoặc xem xét cái gì đó nhiều chuyên như thảo luận ở đây: stackoverflow.com/questions/24534072/...
asgaines

"phân tích cú pháp không rõ ràng trong [if condition]" đã cứu rỗi ngày của tôi, cảm ơn :) coz khi tôi đang thử nó trong fmt.Println (session == Session {}), nó hoạt động.
Franva

37

Dưới đây là 3 gợi ý hoặc kỹ thuật khác:

Với một trường bổ sung

Bạn có thể thêm một trường bổ sung để cho biết liệu cấu trúc đã được điền hay chưa. Tôi cố ý đặt tên cho nó readychứ không phải emptyvì giá trị 0 của a boolfalse, vì vậy nếu bạn tạo một cấu trúc mới như trường Session{}của nó readysẽ tự động falsevà nó sẽ cho bạn biết sự thật: rằng cấu trúc chưa sẵn sàng (nó trống).

type Session struct {
    ready bool

    playerId string
    beehive string
    timestamp time.Time
}

Khi bạn khởi tạo cấu trúc, bạn phải đặt readythành true. isEmpty()Phương thức của bạn không còn cần thiết nữa (mặc dù bạn có thể tạo một phương thức nếu muốn) vì bạn chỉ có thể kiểm tra readychính trường đó.

var s Session

if !s.ready {
    // do stuff (populate s)
}

Tầm quan trọng của một booltrường bổ sung này tăng lên khi cấu trúc lớn hơn hoặc nếu nó chứa các trường không thể so sánh được (ví dụ: mapgiá trị lát cắt và hàm).

Sử dụng giá trị 0 của một trường hiện có

Điều này tương tự như gợi ý trước đó, nhưng nó sử dụng giá trị 0 của trường hiện có được coi là không hợp lệ khi cấu trúc không trống. Khả năng sử dụng của điều này phụ thuộc vào việc thực hiện.

Ví dụ: nếu trong ví dụ của bạn playerIdkhông được để trống string "", bạn có thể sử dụng nó để kiểm tra xem cấu trúc của bạn có trống không như sau:

var s Session

if s.playerId == "" {
    // do stuff (populate s, give proper value to playerId)
}

Trong trường hợp này, nên kết hợp kiểm tra này vào một isEmpty()phương pháp vì kiểm tra này phụ thuộc vào việc triển khai:

func (s Session) isEmpty() bool {
    return s.playerId == ""
}

Và sử dụng nó:

if s.isEmpty() {
    // do stuff (populate s, give proper value to playerId)
}

Sử dụng Con trỏ đến cấu trúc của bạn

Đề nghị thứ hai là sử dụng một con trỏ đến struct của bạn: *Session. Con trỏ có thể có nilcác giá trị, vì vậy bạn có thể kiểm tra nó:

var s *Session

if s == nil {
    s = new(Session)
    // do stuff (populate s)
}

Câu trả lời chính xác. Xin cảm ơn icza!
Evgeny Goldin

Câu trả lời tuyệt vời! Tôi nghĩ rằng việc làm theo sự lựa chọn cuối cùng trông khá ngớ ngẩn.
DeivinsonTejeda

19

Việc sử dụng Refal.deepEqual cũng hoạt động , đặc biệt khi bạn có bản đồ bên trong cấu trúc

package main

import "fmt"
import "time"
import "reflect"

type Session struct {
    playerId string
    beehive string
    timestamp time.Time
}

func (s Session) IsEmpty() bool {
  return reflect.DeepEqual(s,Session{})
}

func main() {
  x := Session{}
  if x.IsEmpty() {
    fmt.Print("is empty")
  } 
}

2
sử dụng phản xạ.DeepEqual là một giải pháp rất sạch sẽ nhưng tôi tự hỏi liệu có mất nhiều thời gian xử lý hơn không? tôi cho rằng nó đang so sánh mọi trường, cộng với việc bạn giới thiệu một nhập mới.
thurt

4

Hãy nhớ rằng với con trỏ đến cấu trúc, bạn phải bỏ qua biến và không so sánh với con trỏ với cấu trúc trống:

session := &Session{}
if (Session{}) == *session {
    fmt.Println("session is empty")
}

Kiểm tra sân chơi này .

Cũng ở đây, bạn có thể thấy rằng một cấu trúc chứa một thuộc tính là một phần của con trỏ không thể được so sánh theo cùng một cách ...


0

Để thay thế cho các câu trả lời khác, bạn có thể thực hiện điều này với cú pháp tương tự như cách bạn dự định ban đầu nếu bạn thực hiện nó thông qua một casecâu lệnh thay vì if:

session := Session{}
switch {
case Session{} == session:
    fmt.Println("zero")
default:
    fmt.Println("not zero")
}

sân chơi ví dụ


0

Chỉ là một bổ sung nhanh chóng, bởi vì tôi đã giải quyết cùng một vấn đề hôm nay:

Với Go 1.13, có thể sử dụng isZero()phương pháp mới :

if reflect.ValueOf(session).IsZero() {
     // do stuff...
}

Tôi đã không kiểm tra điều này liên quan đến hiệu suất, nhưng tôi đoán rằng điều này sẽ nhanh hơn so với so sánh thông qua reflect.DeepEqual().


-1

Có thể như thế này

package main

import "fmt"
import "time"

type Session struct {
    playerId string
    beehive string
    timestamp time.Time
}

func (s Session) Equal(o Session) bool {
   if(s.playerId != o.playerId) { return false }
   if(s.beehive != o.beehive) { return false }
   if(s.timestamp != o.timestamp) { return false }
   return true
}

func (s Session) IsEmpty() bool {
    return s.Equal(Session{})
}

func main() {
    x := Session{}
    if x.IsEmpty() {
       fmt.Print("is empty")
    } 
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.